]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
target-ppc: convert dcr load/store to TCG
[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"
57fec1fe 29#include "tcg-op.h"
ca10f867 30#include "qemu-common.h"
79aceca5 31
a7812ae4
PB
32#include "helper.h"
33#define GEN_HELPER 1
34#include "helper.h"
35
8cbcb4fa
AJ
36#define CPU_SINGLE_STEP 0x1
37#define CPU_BRANCH_STEP 0x2
38#define GDBSTUB_SINGLE_STEP 0x4
39
a750fc0b 40/* Include definitions for instructions classes and implementations flags */
79aceca5 41//#define DO_SINGLE_STEP
9fddaa0c 42//#define PPC_DEBUG_DISAS
76a66253 43//#define DO_PPC_STATISTICS
7c58044c 44//#define OPTIMIZE_FPRF_UPDATE
79aceca5 45
a750fc0b
JM
46/*****************************************************************************/
47/* Code translation helpers */
c53be334 48
f78fb44e 49/* global register indexes */
a7812ae4 50static TCGv_ptr cpu_env;
1d542695 51static char cpu_reg_names[10*3 + 22*4 /* GPR */
f78fb44e 52#if !defined(TARGET_PPC64)
1d542695 53 + 10*4 + 22*5 /* SPE GPRh */
f78fb44e 54#endif
a5e26afa 55 + 10*4 + 22*5 /* FPR */
47e4661c
AJ
56 + 2*(10*6 + 22*7) /* AVRh, AVRl */
57 + 8*5 /* CRF */];
f78fb44e
AJ
58static TCGv cpu_gpr[32];
59#if !defined(TARGET_PPC64)
60static TCGv cpu_gprh[32];
61#endif
a7812ae4
PB
62static TCGv_i64 cpu_fpr[32];
63static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
64static TCGv_i32 cpu_crf[8];
bd568f18 65static TCGv cpu_nip;
6527f6ea 66static TCGv cpu_msr;
cfdcd37a
AJ
67static TCGv cpu_ctr;
68static TCGv cpu_lr;
3d7b417e 69static TCGv cpu_xer;
cf360a32 70static TCGv cpu_reserve;
a7812ae4 71static TCGv_i32 cpu_fpscr;
a7859e89 72static TCGv_i32 cpu_access_type;
f78fb44e
AJ
73
74/* dyngen register indexes */
75static TCGv cpu_T[3];
2e70f6ef
PB
76
77#include "gen-icount.h"
78
79void ppc_translate_init(void)
80{
f78fb44e
AJ
81 int i;
82 char* p;
b2437bf2 83 static int done_init = 0;
f78fb44e 84
2e70f6ef
PB
85 if (done_init)
86 return;
f78fb44e 87
a7812ae4 88 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
1c73fe5b 89#if TARGET_LONG_BITS > HOST_LONG_BITS
a7812ae4
PB
90 cpu_T[0] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t0), "T0");
91 cpu_T[1] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t1), "T1");
92 cpu_T[2] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t2), "T2");
1c73fe5b 93#else
a7812ae4
PB
94 cpu_T[0] = tcg_global_reg_new(TCG_AREG1, "T0");
95 cpu_T[1] = tcg_global_reg_new(TCG_AREG2, "T1");
4870167d
AJ
96#ifdef HOST_I386
97 /* XXX: This is a temporary workaround for i386.
98 * On i386 qemu_st32 runs out of registers.
99 * The proper fix is to remove cpu_T.
100 */
a7812ae4 101 cpu_T[2] = tcg_global_mem_new(TCG_AREG0, offsetof(CPUState, t2), "T2");
4870167d 102#else
a7812ae4 103 cpu_T[2] = tcg_global_reg_new(TCG_AREG3, "T2");
1c73fe5b 104#endif
a7812ae4
PB
105#endif
106
f78fb44e 107 p = cpu_reg_names;
47e4661c
AJ
108
109 for (i = 0; i < 8; i++) {
110 sprintf(p, "crf%d", i);
a7812ae4
PB
111 cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
112 offsetof(CPUState, crf[i]), p);
47e4661c
AJ
113 p += 5;
114 }
115
f78fb44e
AJ
116 for (i = 0; i < 32; i++) {
117 sprintf(p, "r%d", i);
a7812ae4 118 cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
f78fb44e
AJ
119 offsetof(CPUState, gpr[i]), p);
120 p += (i < 10) ? 3 : 4;
121#if !defined(TARGET_PPC64)
122 sprintf(p, "r%dH", i);
a7812ae4
PB
123 cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
124 offsetof(CPUState, gprh[i]), p);
f78fb44e
AJ
125 p += (i < 10) ? 4 : 5;
126#endif
1d542695 127
a5e26afa 128 sprintf(p, "fp%d", i);
a7812ae4
PB
129 cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
130 offsetof(CPUState, fpr[i]), p);
ec1ac72d 131 p += (i < 10) ? 4 : 5;
a5e26afa 132
1d542695 133 sprintf(p, "avr%dH", i);
fe1e5c53
AJ
134#ifdef WORDS_BIGENDIAN
135 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
136 offsetof(CPUState, avr[i].u64[0]), p);
137#else
a7812ae4 138 cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
fe1e5c53
AJ
139 offsetof(CPUState, avr[i].u64[1]), p);
140#endif
1d542695 141 p += (i < 10) ? 6 : 7;
ec1ac72d 142
1d542695 143 sprintf(p, "avr%dL", i);
fe1e5c53
AJ
144#ifdef WORDS_BIGENDIAN
145 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
146 offsetof(CPUState, avr[i].u64[1]), p);
147#else
a7812ae4 148 cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
fe1e5c53
AJ
149 offsetof(CPUState, avr[i].u64[0]), p);
150#endif
1d542695 151 p += (i < 10) ? 6 : 7;
f78fb44e 152 }
f10dc08e 153
a7812ae4 154 cpu_nip = tcg_global_mem_new(TCG_AREG0,
bd568f18
AJ
155 offsetof(CPUState, nip), "nip");
156
6527f6ea
AJ
157 cpu_msr = tcg_global_mem_new(TCG_AREG0,
158 offsetof(CPUState, msr), "msr");
159
a7812ae4 160 cpu_ctr = tcg_global_mem_new(TCG_AREG0,
cfdcd37a
AJ
161 offsetof(CPUState, ctr), "ctr");
162
a7812ae4 163 cpu_lr = tcg_global_mem_new(TCG_AREG0,
cfdcd37a
AJ
164 offsetof(CPUState, lr), "lr");
165
a7812ae4 166 cpu_xer = tcg_global_mem_new(TCG_AREG0,
3d7b417e
AJ
167 offsetof(CPUState, xer), "xer");
168
cf360a32
AJ
169 cpu_reserve = tcg_global_mem_new(TCG_AREG0,
170 offsetof(CPUState, reserve), "reserve");
171
a7812ae4
PB
172 cpu_fpscr = tcg_global_mem_new_i32(TCG_AREG0,
173 offsetof(CPUState, fpscr), "fpscr");
e1571908 174
a7859e89
AJ
175 cpu_access_type = tcg_global_mem_new_i32(TCG_AREG0,
176 offsetof(CPUState, access_type), "access_type");
177
f10dc08e 178 /* register helpers */
a7812ae4 179#define GEN_HELPER 2
f10dc08e
AJ
180#include "helper.h"
181
2e70f6ef
PB
182 done_init = 1;
183}
184
7c58044c
JM
185#if defined(OPTIMIZE_FPRF_UPDATE)
186static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
187static uint16_t **gen_fprf_ptr;
188#endif
79aceca5 189
79aceca5
FB
190/* internal defines */
191typedef struct DisasContext {
192 struct TranslationBlock *tb;
0fa85d43 193 target_ulong nip;
79aceca5 194 uint32_t opcode;
9a64fbe4 195 uint32_t exception;
3cc62370
FB
196 /* Routine used to access memory */
197 int mem_idx;
198 /* Translation flags */
9a64fbe4 199#if !defined(CONFIG_USER_ONLY)
79aceca5 200 int supervisor;
d9bce9d9
JM
201#endif
202#if defined(TARGET_PPC64)
203 int sf_mode;
9a64fbe4 204#endif
3cc62370 205 int fpu_enabled;
a9d9eb8f 206 int altivec_enabled;
0487d6a8 207 int spe_enabled;
3fc6c082 208 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
ea4e754f 209 int singlestep_enabled;
79aceca5
FB
210} DisasContext;
211
3fc6c082 212struct opc_handler_t {
79aceca5
FB
213 /* invalid bits */
214 uint32_t inval;
9a64fbe4 215 /* instruction type */
0487d6a8 216 uint64_t type;
79aceca5
FB
217 /* handler */
218 void (*handler)(DisasContext *ctx);
a750fc0b 219#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
b55266b5 220 const char *oname;
a750fc0b
JM
221#endif
222#if defined(DO_PPC_STATISTICS)
76a66253
JM
223 uint64_t count;
224#endif
3fc6c082 225};
79aceca5 226
7c58044c
JM
227static always_inline void gen_reset_fpstatus (void)
228{
229#ifdef CONFIG_SOFTFLOAT
230 gen_op_reset_fpstatus();
231#endif
232}
233
0f2f39c2 234static always_inline void gen_compute_fprf (TCGv_i64 arg, int set_fprf, int set_rc)
7c58044c 235{
0f2f39c2 236 TCGv_i32 t0 = tcg_temp_new_i32();
af12906f 237
7c58044c
JM
238 if (set_fprf != 0) {
239 /* This case might be optimized later */
240#if defined(OPTIMIZE_FPRF_UPDATE)
241 *gen_fprf_ptr++ = gen_opc_ptr;
242#endif
0f2f39c2 243 tcg_gen_movi_i32(t0, 1);
af12906f 244 gen_helper_compute_fprf(t0, arg, t0);
a7812ae4 245 if (unlikely(set_rc)) {
0f2f39c2 246 tcg_gen_mov_i32(cpu_crf[1], t0);
a7812ae4 247 }
af12906f 248 gen_helper_float_check_status();
7c58044c
JM
249 } else if (unlikely(set_rc)) {
250 /* We always need to compute fpcc */
0f2f39c2 251 tcg_gen_movi_i32(t0, 0);
af12906f 252 gen_helper_compute_fprf(t0, arg, t0);
0f2f39c2 253 tcg_gen_mov_i32(cpu_crf[1], t0);
7c58044c 254 if (set_fprf)
af12906f 255 gen_helper_float_check_status();
7c58044c 256 }
af12906f 257
0f2f39c2 258 tcg_temp_free_i32(t0);
7c58044c
JM
259}
260
261static always_inline void gen_optimize_fprf (void)
262{
263#if defined(OPTIMIZE_FPRF_UPDATE)
264 uint16_t **ptr;
265
266 for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
267 *ptr = INDEX_op_nop1;
268 gen_fprf_ptr = gen_fprf_buf;
269#endif
270}
271
a7859e89
AJ
272static always_inline void gen_set_access_type(int access_type)
273{
274 tcg_gen_movi_i32(cpu_access_type, access_type);
275}
276
b068d6a7 277static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
d9bce9d9
JM
278{
279#if defined(TARGET_PPC64)
280 if (ctx->sf_mode)
bd568f18 281 tcg_gen_movi_tl(cpu_nip, nip);
d9bce9d9
JM
282 else
283#endif
bd568f18 284 tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
d9bce9d9
JM
285}
286
e1833e1f 287#define GEN_EXCP(ctx, excp, error) \
79aceca5 288do { \
64adab3f
AJ
289 TCGv_i32 t0 = tcg_const_i32(excp); \
290 TCGv_i32 t1 = tcg_const_i32(error); \
e1833e1f 291 if ((ctx)->exception == POWERPC_EXCP_NONE) { \
d9bce9d9 292 gen_update_nip(ctx, (ctx)->nip); \
9fddaa0c 293 } \
64adab3f
AJ
294 gen_helper_raise_exception_err(t0, t1); \
295 tcg_temp_free_i32(t0); \
296 tcg_temp_free_i32(t1); \
9fddaa0c 297 ctx->exception = (excp); \
79aceca5
FB
298} while (0)
299
e1833e1f
JM
300#define GEN_EXCP_INVAL(ctx) \
301GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
302 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
9fddaa0c 303
e1833e1f
JM
304#define GEN_EXCP_PRIVOPC(ctx) \
305GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
306 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
9a64fbe4 307
e1833e1f
JM
308#define GEN_EXCP_PRIVREG(ctx) \
309GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
310 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
311
312#define GEN_EXCP_NO_FP(ctx) \
313GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
314
315#define GEN_EXCP_NO_AP(ctx) \
316GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
9a64fbe4 317
a9d9eb8f
JM
318#define GEN_EXCP_NO_VR(ctx) \
319GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
320
f24e5695 321/* Stop translation */
b068d6a7 322static always_inline void GEN_STOP (DisasContext *ctx)
3fc6c082 323{
d9bce9d9 324 gen_update_nip(ctx, ctx->nip);
e1833e1f 325 ctx->exception = POWERPC_EXCP_STOP;
3fc6c082
FB
326}
327
f24e5695 328/* No need to update nip here, as execution flow will change */
b068d6a7 329static always_inline void GEN_SYNC (DisasContext *ctx)
2be0071f 330{
e1833e1f 331 ctx->exception = POWERPC_EXCP_SYNC;
2be0071f
FB
332}
333
79aceca5
FB
334#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
335static void gen_##name (DisasContext *ctx); \
336GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
337static void gen_##name (DisasContext *ctx)
338
c7697e1f
JM
339#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
340static void gen_##name (DisasContext *ctx); \
341GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type); \
342static void gen_##name (DisasContext *ctx)
343
79aceca5
FB
344typedef struct opcode_t {
345 unsigned char opc1, opc2, opc3;
1235fc06 346#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
18fba28c
FB
347 unsigned char pad[5];
348#else
349 unsigned char pad[1];
350#endif
79aceca5 351 opc_handler_t handler;
b55266b5 352 const char *oname;
79aceca5
FB
353} opcode_t;
354
a750fc0b 355/*****************************************************************************/
79aceca5
FB
356/*** Instruction decoding ***/
357#define EXTRACT_HELPER(name, shift, nb) \
b068d6a7 358static always_inline uint32_t name (uint32_t opcode) \
79aceca5
FB
359{ \
360 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
361}
362
363#define EXTRACT_SHELPER(name, shift, nb) \
b068d6a7 364static always_inline int32_t name (uint32_t opcode) \
79aceca5 365{ \
18fba28c 366 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
79aceca5
FB
367}
368
369/* Opcode part 1 */
370EXTRACT_HELPER(opc1, 26, 6);
371/* Opcode part 2 */
372EXTRACT_HELPER(opc2, 1, 5);
373/* Opcode part 3 */
374EXTRACT_HELPER(opc3, 6, 5);
375/* Update Cr0 flags */
376EXTRACT_HELPER(Rc, 0, 1);
377/* Destination */
378EXTRACT_HELPER(rD, 21, 5);
379/* Source */
380EXTRACT_HELPER(rS, 21, 5);
381/* First operand */
382EXTRACT_HELPER(rA, 16, 5);
383/* Second operand */
384EXTRACT_HELPER(rB, 11, 5);
385/* Third operand */
386EXTRACT_HELPER(rC, 6, 5);
387/*** Get CRn ***/
388EXTRACT_HELPER(crfD, 23, 3);
389EXTRACT_HELPER(crfS, 18, 3);
390EXTRACT_HELPER(crbD, 21, 5);
391EXTRACT_HELPER(crbA, 16, 5);
392EXTRACT_HELPER(crbB, 11, 5);
393/* SPR / TBL */
3fc6c082 394EXTRACT_HELPER(_SPR, 11, 10);
b068d6a7 395static always_inline uint32_t SPR (uint32_t opcode)
3fc6c082
FB
396{
397 uint32_t sprn = _SPR(opcode);
398
399 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
400}
79aceca5
FB
401/*** Get constants ***/
402EXTRACT_HELPER(IMM, 12, 8);
403/* 16 bits signed immediate value */
404EXTRACT_SHELPER(SIMM, 0, 16);
405/* 16 bits unsigned immediate value */
406EXTRACT_HELPER(UIMM, 0, 16);
407/* Bit count */
408EXTRACT_HELPER(NB, 11, 5);
409/* Shift count */
410EXTRACT_HELPER(SH, 11, 5);
411/* Mask start */
412EXTRACT_HELPER(MB, 6, 5);
413/* Mask end */
414EXTRACT_HELPER(ME, 1, 5);
fb0eaffc
FB
415/* Trap operand */
416EXTRACT_HELPER(TO, 21, 5);
79aceca5
FB
417
418EXTRACT_HELPER(CRM, 12, 8);
419EXTRACT_HELPER(FM, 17, 8);
420EXTRACT_HELPER(SR, 16, 4);
e4bb997e 421EXTRACT_HELPER(FPIMM, 12, 4);
fb0eaffc 422
79aceca5
FB
423/*** Jump target decoding ***/
424/* Displacement */
425EXTRACT_SHELPER(d, 0, 16);
426/* Immediate address */
b068d6a7 427static always_inline target_ulong LI (uint32_t opcode)
79aceca5
FB
428{
429 return (opcode >> 0) & 0x03FFFFFC;
430}
431
b068d6a7 432static always_inline uint32_t BD (uint32_t opcode)
79aceca5
FB
433{
434 return (opcode >> 0) & 0xFFFC;
435}
436
437EXTRACT_HELPER(BO, 21, 5);
438EXTRACT_HELPER(BI, 16, 5);
439/* Absolute/relative address */
440EXTRACT_HELPER(AA, 1, 1);
441/* Link */
442EXTRACT_HELPER(LK, 0, 1);
443
444/* Create a mask between <start> and <end> bits */
b068d6a7 445static always_inline target_ulong MASK (uint32_t start, uint32_t end)
79aceca5 446{
76a66253 447 target_ulong ret;
79aceca5 448
76a66253
JM
449#if defined(TARGET_PPC64)
450 if (likely(start == 0)) {
6f2d8978 451 ret = UINT64_MAX << (63 - end);
76a66253 452 } else if (likely(end == 63)) {
6f2d8978 453 ret = UINT64_MAX >> start;
76a66253
JM
454 }
455#else
456 if (likely(start == 0)) {
6f2d8978 457 ret = UINT32_MAX << (31 - end);
76a66253 458 } else if (likely(end == 31)) {
6f2d8978 459 ret = UINT32_MAX >> start;
76a66253
JM
460 }
461#endif
462 else {
463 ret = (((target_ulong)(-1ULL)) >> (start)) ^
464 (((target_ulong)(-1ULL) >> (end)) >> 1);
465 if (unlikely(start > end))
466 return ~ret;
467 }
79aceca5
FB
468
469 return ret;
470}
471
a750fc0b
JM
472/*****************************************************************************/
473/* PowerPC Instructions types definitions */
474enum {
1b413d55 475 PPC_NONE = 0x0000000000000000ULL,
12de9a39 476 /* PowerPC base instructions set */
1b413d55
JM
477 PPC_INSNS_BASE = 0x0000000000000001ULL,
478 /* integer operations instructions */
a750fc0b 479#define PPC_INTEGER PPC_INSNS_BASE
1b413d55 480 /* flow control instructions */
a750fc0b 481#define PPC_FLOW PPC_INSNS_BASE
1b413d55 482 /* virtual memory instructions */
a750fc0b 483#define PPC_MEM PPC_INSNS_BASE
1b413d55 484 /* ld/st with reservation instructions */
a750fc0b 485#define PPC_RES PPC_INSNS_BASE
1b413d55 486 /* spr/msr access instructions */
a750fc0b 487#define PPC_MISC PPC_INSNS_BASE
1b413d55
JM
488 /* Deprecated instruction sets */
489 /* Original POWER instruction set */
f610349f 490 PPC_POWER = 0x0000000000000002ULL,
1b413d55 491 /* POWER2 instruction set extension */
f610349f 492 PPC_POWER2 = 0x0000000000000004ULL,
1b413d55 493 /* Power RTC support */
f610349f 494 PPC_POWER_RTC = 0x0000000000000008ULL,
1b413d55 495 /* Power-to-PowerPC bridge (601) */
f610349f 496 PPC_POWER_BR = 0x0000000000000010ULL,
1b413d55 497 /* 64 bits PowerPC instruction set */
f610349f 498 PPC_64B = 0x0000000000000020ULL,
1b413d55 499 /* New 64 bits extensions (PowerPC 2.0x) */
f610349f 500 PPC_64BX = 0x0000000000000040ULL,
1b413d55 501 /* 64 bits hypervisor extensions */
f610349f 502 PPC_64H = 0x0000000000000080ULL,
1b413d55 503 /* New wait instruction (PowerPC 2.0x) */
f610349f 504 PPC_WAIT = 0x0000000000000100ULL,
1b413d55 505 /* Time base mftb instruction */
f610349f 506 PPC_MFTB = 0x0000000000000200ULL,
1b413d55
JM
507
508 /* Fixed-point unit extensions */
509 /* PowerPC 602 specific */
f610349f 510 PPC_602_SPEC = 0x0000000000000400ULL,
05332d70
JM
511 /* isel instruction */
512 PPC_ISEL = 0x0000000000000800ULL,
513 /* popcntb instruction */
514 PPC_POPCNTB = 0x0000000000001000ULL,
515 /* string load / store */
516 PPC_STRING = 0x0000000000002000ULL,
1b413d55
JM
517
518 /* Floating-point unit extensions */
519 /* Optional floating point instructions */
520 PPC_FLOAT = 0x0000000000010000ULL,
521 /* New floating-point extensions (PowerPC 2.0x) */
522 PPC_FLOAT_EXT = 0x0000000000020000ULL,
523 PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
524 PPC_FLOAT_FRES = 0x0000000000080000ULL,
525 PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
526 PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
527 PPC_FLOAT_FSEL = 0x0000000000400000ULL,
528 PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
529
530 /* Vector/SIMD extensions */
531 /* Altivec support */
532 PPC_ALTIVEC = 0x0000000001000000ULL,
1b413d55 533 /* PowerPC 2.03 SPE extension */
05332d70 534 PPC_SPE = 0x0000000002000000ULL,
1b413d55 535 /* PowerPC 2.03 SPE floating-point extension */
05332d70 536 PPC_SPEFPU = 0x0000000004000000ULL,
1b413d55 537
12de9a39 538 /* Optional memory control instructions */
1b413d55
JM
539 PPC_MEM_TLBIA = 0x0000000010000000ULL,
540 PPC_MEM_TLBIE = 0x0000000020000000ULL,
541 PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
542 /* sync instruction */
543 PPC_MEM_SYNC = 0x0000000080000000ULL,
544 /* eieio instruction */
545 PPC_MEM_EIEIO = 0x0000000100000000ULL,
546
547 /* Cache control instructions */
c8623f2e 548 PPC_CACHE = 0x0000000200000000ULL,
1b413d55 549 /* icbi instruction */
05332d70 550 PPC_CACHE_ICBI = 0x0000000400000000ULL,
1b413d55 551 /* dcbz instruction with fixed cache line size */
05332d70 552 PPC_CACHE_DCBZ = 0x0000000800000000ULL,
1b413d55 553 /* dcbz instruction with tunable cache line size */
05332d70 554 PPC_CACHE_DCBZT = 0x0000001000000000ULL,
1b413d55 555 /* dcba instruction */
05332d70
JM
556 PPC_CACHE_DCBA = 0x0000002000000000ULL,
557 /* Freescale cache locking instructions */
558 PPC_CACHE_LOCK = 0x0000004000000000ULL,
1b413d55
JM
559
560 /* MMU related extensions */
561 /* external control instructions */
05332d70 562 PPC_EXTERN = 0x0000010000000000ULL,
1b413d55 563 /* segment register access instructions */
05332d70 564 PPC_SEGMENT = 0x0000020000000000ULL,
1b413d55 565 /* PowerPC 6xx TLB management instructions */
05332d70 566 PPC_6xx_TLB = 0x0000040000000000ULL,
1b413d55 567 /* PowerPC 74xx TLB management instructions */
05332d70 568 PPC_74xx_TLB = 0x0000080000000000ULL,
1b413d55 569 /* PowerPC 40x TLB management instructions */
05332d70 570 PPC_40x_TLB = 0x0000100000000000ULL,
1b413d55 571 /* segment register access instructions for PowerPC 64 "bridge" */
05332d70 572 PPC_SEGMENT_64B = 0x0000200000000000ULL,
1b413d55 573 /* SLB management */
05332d70 574 PPC_SLBI = 0x0000400000000000ULL,
1b413d55 575
12de9a39 576 /* Embedded PowerPC dedicated instructions */
05332d70 577 PPC_WRTEE = 0x0001000000000000ULL,
12de9a39 578 /* PowerPC 40x exception model */
05332d70 579 PPC_40x_EXCP = 0x0002000000000000ULL,
12de9a39 580 /* PowerPC 405 Mac instructions */
05332d70 581 PPC_405_MAC = 0x0004000000000000ULL,
12de9a39 582 /* PowerPC 440 specific instructions */
05332d70 583 PPC_440_SPEC = 0x0008000000000000ULL,
12de9a39 584 /* BookE (embedded) PowerPC specification */
05332d70
JM
585 PPC_BOOKE = 0x0010000000000000ULL,
586 /* mfapidi instruction */
587 PPC_MFAPIDI = 0x0020000000000000ULL,
588 /* tlbiva instruction */
589 PPC_TLBIVA = 0x0040000000000000ULL,
590 /* tlbivax instruction */
591 PPC_TLBIVAX = 0x0080000000000000ULL,
12de9a39 592 /* PowerPC 4xx dedicated instructions */
05332d70 593 PPC_4xx_COMMON = 0x0100000000000000ULL,
12de9a39 594 /* PowerPC 40x ibct instructions */
05332d70 595 PPC_40x_ICBT = 0x0200000000000000ULL,
12de9a39 596 /* rfmci is not implemented in all BookE PowerPC */
05332d70
JM
597 PPC_RFMCI = 0x0400000000000000ULL,
598 /* rfdi instruction */
599 PPC_RFDI = 0x0800000000000000ULL,
600 /* DCR accesses */
601 PPC_DCR = 0x1000000000000000ULL,
602 /* DCR extended accesse */
603 PPC_DCRX = 0x2000000000000000ULL,
12de9a39 604 /* user-mode DCR access, implemented in PowerPC 460 */
05332d70 605 PPC_DCRUX = 0x4000000000000000ULL,
a750fc0b
JM
606};
607
608/*****************************************************************************/
609/* PowerPC instructions table */
3fc6c082
FB
610#if HOST_LONG_BITS == 64
611#define OPC_ALIGN 8
612#else
613#define OPC_ALIGN 4
614#endif
1b039c09 615#if defined(__APPLE__)
d9bce9d9 616#define OPCODES_SECTION \
3fc6c082 617 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
933dc6eb 618#else
d9bce9d9 619#define OPCODES_SECTION \
3fc6c082 620 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
933dc6eb
FB
621#endif
622
76a66253 623#if defined(DO_PPC_STATISTICS)
79aceca5 624#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
18fba28c 625OPCODES_SECTION opcode_t opc_##name = { \
79aceca5
FB
626 .opc1 = op1, \
627 .opc2 = op2, \
628 .opc3 = op3, \
18fba28c 629 .pad = { 0, }, \
79aceca5
FB
630 .handler = { \
631 .inval = invl, \
9a64fbe4 632 .type = _typ, \
79aceca5 633 .handler = &gen_##name, \
76a66253 634 .oname = stringify(name), \
79aceca5 635 }, \
3fc6c082 636 .oname = stringify(name), \
79aceca5 637}
c7697e1f
JM
638#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
639OPCODES_SECTION opcode_t opc_##name = { \
640 .opc1 = op1, \
641 .opc2 = op2, \
642 .opc3 = op3, \
643 .pad = { 0, }, \
644 .handler = { \
645 .inval = invl, \
646 .type = _typ, \
647 .handler = &gen_##name, \
648 .oname = onam, \
649 }, \
650 .oname = onam, \
651}
76a66253
JM
652#else
653#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
654OPCODES_SECTION opcode_t opc_##name = { \
655 .opc1 = op1, \
656 .opc2 = op2, \
657 .opc3 = op3, \
658 .pad = { 0, }, \
659 .handler = { \
660 .inval = invl, \
661 .type = _typ, \
662 .handler = &gen_##name, \
663 }, \
664 .oname = stringify(name), \
665}
c7697e1f
JM
666#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
667OPCODES_SECTION opcode_t opc_##name = { \
668 .opc1 = op1, \
669 .opc2 = op2, \
670 .opc3 = op3, \
671 .pad = { 0, }, \
672 .handler = { \
673 .inval = invl, \
674 .type = _typ, \
675 .handler = &gen_##name, \
676 }, \
677 .oname = onam, \
678}
76a66253 679#endif
79aceca5
FB
680
681#define GEN_OPCODE_MARK(name) \
18fba28c 682OPCODES_SECTION opcode_t opc_##name = { \
79aceca5
FB
683 .opc1 = 0xFF, \
684 .opc2 = 0xFF, \
685 .opc3 = 0xFF, \
18fba28c 686 .pad = { 0, }, \
79aceca5
FB
687 .handler = { \
688 .inval = 0x00000000, \
9a64fbe4 689 .type = 0x00, \
79aceca5
FB
690 .handler = NULL, \
691 }, \
3fc6c082 692 .oname = stringify(name), \
79aceca5
FB
693}
694
54cdcae6
AJ
695/* SPR load/store helpers */
696static always_inline void gen_load_spr(TCGv t, int reg)
697{
698 tcg_gen_ld_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
699}
700
701static always_inline void gen_store_spr(int reg, TCGv t)
702{
703 tcg_gen_st_tl(t, cpu_env, offsetof(CPUState, spr[reg]));
704}
705
79aceca5
FB
706/* Start opcode list */
707GEN_OPCODE_MARK(start);
708
709/* Invalid instruction */
9a64fbe4
FB
710GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
711{
e1833e1f 712 GEN_EXCP_INVAL(ctx);
9a64fbe4
FB
713}
714
79aceca5
FB
715static opc_handler_t invalid_handler = {
716 .inval = 0xFFFFFFFF,
9a64fbe4 717 .type = PPC_NONE,
79aceca5
FB
718 .handler = gen_invalid,
719};
720
e1571908
AJ
721/*** Integer comparison ***/
722
ea363694 723static always_inline void gen_op_cmp(TCGv arg0, TCGv arg1, int s, int crf)
e1571908
AJ
724{
725 int l1, l2, l3;
726
269f3e95
AJ
727 tcg_gen_trunc_tl_i32(cpu_crf[crf], cpu_xer);
728 tcg_gen_shri_i32(cpu_crf[crf], cpu_crf[crf], XER_SO);
e1571908
AJ
729 tcg_gen_andi_i32(cpu_crf[crf], cpu_crf[crf], 1);
730
731 l1 = gen_new_label();
732 l2 = gen_new_label();
733 l3 = gen_new_label();
734 if (s) {
ea363694
AJ
735 tcg_gen_brcond_tl(TCG_COND_LT, arg0, arg1, l1);
736 tcg_gen_brcond_tl(TCG_COND_GT, arg0, arg1, l2);
e1571908 737 } else {
ea363694
AJ
738 tcg_gen_brcond_tl(TCG_COND_LTU, arg0, arg1, l1);
739 tcg_gen_brcond_tl(TCG_COND_GTU, arg0, arg1, l2);
e1571908
AJ
740 }
741 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_EQ);
742 tcg_gen_br(l3);
743 gen_set_label(l1);
744 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_LT);
745 tcg_gen_br(l3);
746 gen_set_label(l2);
747 tcg_gen_ori_i32(cpu_crf[crf], cpu_crf[crf], 1 << CRF_GT);
748 gen_set_label(l3);
749}
750
ea363694 751static always_inline void gen_op_cmpi(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 752{
ea363694
AJ
753 TCGv t0 = tcg_const_local_tl(arg1);
754 gen_op_cmp(arg0, t0, s, crf);
755 tcg_temp_free(t0);
e1571908
AJ
756}
757
758#if defined(TARGET_PPC64)
ea363694 759static always_inline void gen_op_cmp32(TCGv arg0, TCGv arg1, int s, int crf)
e1571908 760{
ea363694 761 TCGv t0, t1;
a7812ae4
PB
762 t0 = tcg_temp_local_new();
763 t1 = tcg_temp_local_new();
e1571908 764 if (s) {
ea363694
AJ
765 tcg_gen_ext32s_tl(t0, arg0);
766 tcg_gen_ext32s_tl(t1, arg1);
e1571908 767 } else {
ea363694
AJ
768 tcg_gen_ext32u_tl(t0, arg0);
769 tcg_gen_ext32u_tl(t1, arg1);
e1571908 770 }
ea363694
AJ
771 gen_op_cmp(t0, t1, s, crf);
772 tcg_temp_free(t1);
773 tcg_temp_free(t0);
e1571908
AJ
774}
775
ea363694 776static always_inline void gen_op_cmpi32(TCGv arg0, target_ulong arg1, int s, int crf)
e1571908 777{
ea363694
AJ
778 TCGv t0 = tcg_const_local_tl(arg1);
779 gen_op_cmp32(arg0, t0, s, crf);
780 tcg_temp_free(t0);
e1571908
AJ
781}
782#endif
783
784static always_inline void gen_set_Rc0 (DisasContext *ctx, TCGv reg)
785{
786#if defined(TARGET_PPC64)
787 if (!(ctx->sf_mode))
788 gen_op_cmpi32(reg, 0, 1, 0);
789 else
790#endif
791 gen_op_cmpi(reg, 0, 1, 0);
792}
793
794/* cmp */
795GEN_HANDLER(cmp, 0x1F, 0x00, 0x00, 0x00400000, PPC_INTEGER)
796{
797#if defined(TARGET_PPC64)
798 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
799 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
800 1, crfD(ctx->opcode));
801 else
802#endif
803 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
804 1, crfD(ctx->opcode));
805}
806
807/* cmpi */
808GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
809{
810#if defined(TARGET_PPC64)
811 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
812 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
813 1, crfD(ctx->opcode));
814 else
815#endif
816 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], SIMM(ctx->opcode),
817 1, crfD(ctx->opcode));
818}
819
820/* cmpl */
821GEN_HANDLER(cmpl, 0x1F, 0x00, 0x01, 0x00400000, PPC_INTEGER)
822{
823#if defined(TARGET_PPC64)
824 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
825 gen_op_cmp32(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
826 0, crfD(ctx->opcode));
827 else
828#endif
829 gen_op_cmp(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)],
830 0, crfD(ctx->opcode));
831}
832
833/* cmpli */
834GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
835{
836#if defined(TARGET_PPC64)
837 if (!(ctx->sf_mode && (ctx->opcode & 0x00200000)))
838 gen_op_cmpi32(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
839 0, crfD(ctx->opcode));
840 else
841#endif
842 gen_op_cmpi(cpu_gpr[rA(ctx->opcode)], UIMM(ctx->opcode),
843 0, crfD(ctx->opcode));
844}
845
846/* isel (PowerPC 2.03 specification) */
847GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
848{
849 int l1, l2;
850 uint32_t bi = rC(ctx->opcode);
851 uint32_t mask;
a7812ae4 852 TCGv_i32 t0;
e1571908
AJ
853
854 l1 = gen_new_label();
855 l2 = gen_new_label();
856
857 mask = 1 << (3 - (bi & 0x03));
a7812ae4 858 t0 = tcg_temp_new_i32();
fea0c503
AJ
859 tcg_gen_andi_i32(t0, cpu_crf[bi >> 2], mask);
860 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
e1571908
AJ
861 if (rA(ctx->opcode) == 0)
862 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
863 else
864 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
865 tcg_gen_br(l2);
866 gen_set_label(l1);
867 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
868 gen_set_label(l2);
a7812ae4 869 tcg_temp_free_i32(t0);
e1571908
AJ
870}
871
79aceca5 872/*** Integer arithmetic ***/
79aceca5 873
74637406
AJ
874static always_inline void gen_op_arith_compute_ov(DisasContext *ctx, TCGv arg0, TCGv arg1, TCGv arg2, int sub)
875{
876 int l1;
877 TCGv t0;
79aceca5 878
74637406
AJ
879 l1 = gen_new_label();
880 /* Start with XER OV disabled, the most likely case */
881 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
a7812ae4 882 t0 = tcg_temp_local_new();
74637406
AJ
883 tcg_gen_xor_tl(t0, arg0, arg1);
884#if defined(TARGET_PPC64)
885 if (!ctx->sf_mode)
886 tcg_gen_ext32s_tl(t0, t0);
887#endif
888 if (sub)
889 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
890 else
891 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
892 tcg_gen_xor_tl(t0, arg1, arg2);
893#if defined(TARGET_PPC64)
894 if (!ctx->sf_mode)
895 tcg_gen_ext32s_tl(t0, t0);
896#endif
897 if (sub)
898 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
899 else
900 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0, l1);
901 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
902 gen_set_label(l1);
903 tcg_temp_free(t0);
79aceca5
FB
904}
905
74637406
AJ
906static always_inline void gen_op_arith_compute_ca(DisasContext *ctx, TCGv arg1, TCGv arg2, int sub)
907{
908 int l1 = gen_new_label();
d9bce9d9
JM
909
910#if defined(TARGET_PPC64)
74637406
AJ
911 if (!(ctx->sf_mode)) {
912 TCGv t0, t1;
a7812ae4
PB
913 t0 = tcg_temp_new();
914 t1 = tcg_temp_new();
d9bce9d9 915
74637406
AJ
916 tcg_gen_ext32u_tl(t0, arg1);
917 tcg_gen_ext32u_tl(t1, arg2);
918 if (sub) {
919 tcg_gen_brcond_tl(TCG_COND_GTU, t0, t1, l1);
bdc4e053 920 } else {
74637406
AJ
921 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
922 }
a9730017
AJ
923 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
924 gen_set_label(l1);
925 tcg_temp_free(t0);
926 tcg_temp_free(t1);
74637406
AJ
927 } else
928#endif
a9730017
AJ
929 {
930 if (sub) {
931 tcg_gen_brcond_tl(TCG_COND_GTU, arg1, arg2, l1);
932 } else {
933 tcg_gen_brcond_tl(TCG_COND_GEU, arg1, arg2, l1);
934 }
935 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
936 gen_set_label(l1);
74637406 937 }
d9bce9d9
JM
938}
939
74637406
AJ
940/* Common add function */
941static always_inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
942 int add_ca, int compute_ca, int compute_ov)
943{
944 TCGv t0, t1;
d9bce9d9 945
74637406 946 if ((!compute_ca && !compute_ov) ||
a7812ae4 947 (!TCGV_EQUAL(ret,arg1) && !TCGV_EQUAL(ret, arg2))) {
74637406
AJ
948 t0 = ret;
949 } else {
a7812ae4 950 t0 = tcg_temp_local_new();
74637406 951 }
79aceca5 952
74637406 953 if (add_ca) {
a7812ae4 954 t1 = tcg_temp_local_new();
74637406
AJ
955 tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
956 tcg_gen_shri_tl(t1, t1, XER_CA);
957 }
79aceca5 958
74637406
AJ
959 if (compute_ca && compute_ov) {
960 /* Start with XER CA and OV disabled, the most likely case */
961 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
962 } else if (compute_ca) {
963 /* Start with XER CA disabled, the most likely case */
964 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
965 } else if (compute_ov) {
966 /* Start with XER OV disabled, the most likely case */
967 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
968 }
79aceca5 969
74637406
AJ
970 tcg_gen_add_tl(t0, arg1, arg2);
971
972 if (compute_ca) {
973 gen_op_arith_compute_ca(ctx, t0, arg1, 0);
974 }
975 if (add_ca) {
976 tcg_gen_add_tl(t0, t0, t1);
977 gen_op_arith_compute_ca(ctx, t0, t1, 0);
978 tcg_temp_free(t1);
979 }
980 if (compute_ov) {
981 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 0);
982 }
983
984 if (unlikely(Rc(ctx->opcode) != 0))
985 gen_set_Rc0(ctx, t0);
986
a7812ae4 987 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
988 tcg_gen_mov_tl(ret, t0);
989 tcg_temp_free(t0);
990 }
39dd32ee 991}
74637406
AJ
992/* Add functions with two operands */
993#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
994GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER) \
995{ \
996 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
997 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
998 add_ca, compute_ca, compute_ov); \
999}
1000/* Add functions with one operand and one immediate */
1001#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
1002 add_ca, compute_ca, compute_ov) \
1003GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER) \
1004{ \
1005 TCGv t0 = tcg_const_local_tl(const_val); \
1006 gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
1007 cpu_gpr[rA(ctx->opcode)], t0, \
1008 add_ca, compute_ca, compute_ov); \
1009 tcg_temp_free(t0); \
1010}
1011
1012/* add add. addo addo. */
1013GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
1014GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
1015/* addc addc. addco addco. */
1016GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
1017GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
1018/* adde adde. addeo addeo. */
1019GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
1020GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
1021/* addme addme. addmeo addmeo. */
1022GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
1023GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
1024/* addze addze. addzeo addzeo.*/
1025GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
1026GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
1027/* addi */
1028GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
d9bce9d9 1029{
74637406
AJ
1030 target_long simm = SIMM(ctx->opcode);
1031
1032 if (rA(ctx->opcode) == 0) {
1033 /* li case */
1034 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm);
1035 } else {
1036 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm);
1037 }
d9bce9d9 1038}
74637406
AJ
1039/* addic addic.*/
1040static always_inline void gen_op_addic (DisasContext *ctx, TCGv ret, TCGv arg1,
1041 int compute_Rc0)
d9bce9d9 1042{
74637406
AJ
1043 target_long simm = SIMM(ctx->opcode);
1044
1045 /* Start with XER CA and OV disabled, the most likely case */
1046 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1047
1048 if (likely(simm != 0)) {
a7812ae4 1049 TCGv t0 = tcg_temp_local_new();
74637406
AJ
1050 tcg_gen_addi_tl(t0, arg1, simm);
1051 gen_op_arith_compute_ca(ctx, t0, arg1, 0);
1052 tcg_gen_mov_tl(ret, t0);
1053 tcg_temp_free(t0);
1054 } else {
1055 tcg_gen_mov_tl(ret, arg1);
1056 }
1057 if (compute_Rc0) {
1058 gen_set_Rc0(ctx, ret);
1059 }
d9bce9d9 1060}
74637406 1061GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
d9bce9d9 1062{
74637406 1063 gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
d9bce9d9 1064}
74637406 1065GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
d9bce9d9 1066{
74637406 1067 gen_op_addic(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
d9bce9d9 1068}
74637406
AJ
1069/* addis */
1070GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
d9bce9d9 1071{
74637406
AJ
1072 target_long simm = SIMM(ctx->opcode);
1073
1074 if (rA(ctx->opcode) == 0) {
1075 /* lis case */
1076 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], simm << 16);
1077 } else {
1078 tcg_gen_addi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], simm << 16);
1079 }
d9bce9d9 1080}
74637406
AJ
1081
1082static always_inline void gen_op_arith_divw (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1083 int sign, int compute_ov)
d9bce9d9 1084{
2ef1b120
AJ
1085 int l1 = gen_new_label();
1086 int l2 = gen_new_label();
a7812ae4
PB
1087 TCGv_i32 t0 = tcg_temp_local_new_i32();
1088 TCGv_i32 t1 = tcg_temp_local_new_i32();
74637406 1089
2ef1b120
AJ
1090 tcg_gen_trunc_tl_i32(t0, arg1);
1091 tcg_gen_trunc_tl_i32(t1, arg2);
1092 tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l1);
74637406 1093 if (sign) {
2ef1b120
AJ
1094 int l3 = gen_new_label();
1095 tcg_gen_brcondi_i32(TCG_COND_NE, t1, -1, l3);
1096 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, INT32_MIN, l1);
74637406 1097 gen_set_label(l3);
2ef1b120 1098 tcg_gen_div_i32(t0, t0, t1);
74637406 1099 } else {
2ef1b120 1100 tcg_gen_divu_i32(t0, t0, t1);
74637406
AJ
1101 }
1102 if (compute_ov) {
1103 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1104 }
1105 tcg_gen_br(l2);
1106 gen_set_label(l1);
1107 if (sign) {
2ef1b120 1108 tcg_gen_sari_i32(t0, t0, 31);
74637406
AJ
1109 } else {
1110 tcg_gen_movi_i32(t0, 0);
1111 }
1112 if (compute_ov) {
1113 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1114 }
1115 gen_set_label(l2);
2ef1b120 1116 tcg_gen_extu_i32_tl(ret, t0);
a7812ae4
PB
1117 tcg_temp_free_i32(t0);
1118 tcg_temp_free_i32(t1);
74637406
AJ
1119 if (unlikely(Rc(ctx->opcode) != 0))
1120 gen_set_Rc0(ctx, ret);
d9bce9d9 1121}
74637406
AJ
1122/* Div functions */
1123#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
1124GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER) \
1125{ \
1126 gen_op_arith_divw(ctx, cpu_gpr[rD(ctx->opcode)], \
1127 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1128 sign, compute_ov); \
1129}
1130/* divwu divwu. divwuo divwuo. */
1131GEN_INT_ARITH_DIVW(divwu, 0x0E, 0, 0);
1132GEN_INT_ARITH_DIVW(divwuo, 0x1E, 0, 1);
1133/* divw divw. divwo divwo. */
1134GEN_INT_ARITH_DIVW(divw, 0x0F, 1, 0);
1135GEN_INT_ARITH_DIVW(divwo, 0x1F, 1, 1);
d9bce9d9 1136#if defined(TARGET_PPC64)
2ef1b120
AJ
1137static always_inline void gen_op_arith_divd (DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1138 int sign, int compute_ov)
d9bce9d9 1139{
2ef1b120
AJ
1140 int l1 = gen_new_label();
1141 int l2 = gen_new_label();
74637406
AJ
1142
1143 tcg_gen_brcondi_i64(TCG_COND_EQ, arg2, 0, l1);
1144 if (sign) {
2ef1b120 1145 int l3 = gen_new_label();
74637406
AJ
1146 tcg_gen_brcondi_i64(TCG_COND_NE, arg2, -1, l3);
1147 tcg_gen_brcondi_i64(TCG_COND_EQ, arg1, INT64_MIN, l1);
1148 gen_set_label(l3);
74637406
AJ
1149 tcg_gen_div_i64(ret, arg1, arg2);
1150 } else {
1151 tcg_gen_divu_i64(ret, arg1, arg2);
1152 }
1153 if (compute_ov) {
1154 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1155 }
1156 tcg_gen_br(l2);
1157 gen_set_label(l1);
1158 if (sign) {
1159 tcg_gen_sari_i64(ret, arg1, 63);
1160 } else {
1161 tcg_gen_movi_i64(ret, 0);
1162 }
1163 if (compute_ov) {
1164 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1165 }
1166 gen_set_label(l2);
1167 if (unlikely(Rc(ctx->opcode) != 0))
1168 gen_set_Rc0(ctx, ret);
d9bce9d9 1169}
74637406
AJ
1170#define GEN_INT_ARITH_DIVD(name, opc3, sign, compute_ov) \
1171GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B) \
1172{ \
2ef1b120
AJ
1173 gen_op_arith_divd(ctx, cpu_gpr[rD(ctx->opcode)], \
1174 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1175 sign, compute_ov); \
74637406
AJ
1176}
1177/* divwu divwu. divwuo divwuo. */
1178GEN_INT_ARITH_DIVD(divdu, 0x0E, 0, 0);
1179GEN_INT_ARITH_DIVD(divduo, 0x1E, 0, 1);
1180/* divw divw. divwo divwo. */
1181GEN_INT_ARITH_DIVD(divd, 0x0F, 1, 0);
1182GEN_INT_ARITH_DIVD(divdo, 0x1F, 1, 1);
d9bce9d9 1183#endif
74637406
AJ
1184
1185/* mulhw mulhw. */
1186GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER)
d9bce9d9 1187{
a7812ae4 1188 TCGv_i64 t0, t1;
74637406 1189
a7812ae4
PB
1190 t0 = tcg_temp_new_i64();
1191 t1 = tcg_temp_new_i64();
74637406
AJ
1192#if defined(TARGET_PPC64)
1193 tcg_gen_ext32s_tl(t0, cpu_gpr[rA(ctx->opcode)]);
1194 tcg_gen_ext32s_tl(t1, cpu_gpr[rB(ctx->opcode)]);
1195 tcg_gen_mul_i64(t0, t0, t1);
1196 tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1197#else
1198 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1199 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1200 tcg_gen_mul_i64(t0, t0, t1);
1201 tcg_gen_shri_i64(t0, t0, 32);
1202 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1203#endif
a7812ae4
PB
1204 tcg_temp_free_i64(t0);
1205 tcg_temp_free_i64(t1);
74637406
AJ
1206 if (unlikely(Rc(ctx->opcode) != 0))
1207 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1208}
74637406
AJ
1209/* mulhwu mulhwu. */
1210GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER)
d9bce9d9 1211{
a7812ae4 1212 TCGv_i64 t0, t1;
74637406 1213
a7812ae4
PB
1214 t0 = tcg_temp_new_i64();
1215 t1 = tcg_temp_new_i64();
d9bce9d9 1216#if defined(TARGET_PPC64)
74637406
AJ
1217 tcg_gen_ext32u_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1218 tcg_gen_ext32u_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1219 tcg_gen_mul_i64(t0, t0, t1);
1220 tcg_gen_shri_i64(cpu_gpr[rD(ctx->opcode)], t0, 32);
1221#else
1222 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1223 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1224 tcg_gen_mul_i64(t0, t0, t1);
1225 tcg_gen_shri_i64(t0, t0, 32);
1226 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1227#endif
a7812ae4
PB
1228 tcg_temp_free_i64(t0);
1229 tcg_temp_free_i64(t1);
74637406
AJ
1230 if (unlikely(Rc(ctx->opcode) != 0))
1231 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1232}
74637406
AJ
1233/* mullw mullw. */
1234GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER)
d9bce9d9 1235{
74637406
AJ
1236 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1237 cpu_gpr[rB(ctx->opcode)]);
1e4c090f 1238 tcg_gen_ext32s_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)]);
74637406
AJ
1239 if (unlikely(Rc(ctx->opcode) != 0))
1240 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1241}
74637406
AJ
1242/* mullwo mullwo. */
1243GEN_HANDLER(mullwo, 0x1F, 0x0B, 0x17, 0x00000000, PPC_INTEGER)
d9bce9d9 1244{
74637406 1245 int l1;
a7812ae4 1246 TCGv_i64 t0, t1;
74637406 1247
a7812ae4
PB
1248 t0 = tcg_temp_new_i64();
1249 t1 = tcg_temp_new_i64();
74637406
AJ
1250 l1 = gen_new_label();
1251 /* Start with XER OV disabled, the most likely case */
1252 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1253#if defined(TARGET_PPC64)
1254 tcg_gen_ext32s_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1255 tcg_gen_ext32s_i64(t1, cpu_gpr[rB(ctx->opcode)]);
1256#else
1257 tcg_gen_ext_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
1258 tcg_gen_ext_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
d9bce9d9 1259#endif
74637406
AJ
1260 tcg_gen_mul_i64(t0, t0, t1);
1261#if defined(TARGET_PPC64)
1262 tcg_gen_ext32s_i64(cpu_gpr[rD(ctx->opcode)], t0);
1263 tcg_gen_brcond_i64(TCG_COND_EQ, t0, cpu_gpr[rD(ctx->opcode)], l1);
1264#else
1265 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t0);
1266 tcg_gen_ext32s_i64(t1, t0);
1267 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
1268#endif
1269 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1270 gen_set_label(l1);
a7812ae4
PB
1271 tcg_temp_free_i64(t0);
1272 tcg_temp_free_i64(t1);
74637406
AJ
1273 if (unlikely(Rc(ctx->opcode) != 0))
1274 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1275}
74637406
AJ
1276/* mulli */
1277GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
d9bce9d9 1278{
74637406
AJ
1279 tcg_gen_muli_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1280 SIMM(ctx->opcode));
d9bce9d9
JM
1281}
1282#if defined(TARGET_PPC64)
74637406
AJ
1283#define GEN_INT_ARITH_MUL_HELPER(name, opc3) \
1284GEN_HANDLER(name, 0x1F, 0x09, opc3, 0x00000000, PPC_64B) \
1285{ \
a7812ae4 1286 gen_helper_##name (cpu_gpr[rD(ctx->opcode)], \
74637406
AJ
1287 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
1288 if (unlikely(Rc(ctx->opcode) != 0)) \
1289 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]); \
d9bce9d9 1290}
74637406
AJ
1291/* mulhd mulhd. */
1292GEN_INT_ARITH_MUL_HELPER(mulhdu, 0x00);
1293/* mulhdu mulhdu. */
1294GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02);
1295/* mulld mulld. */
1296GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B)
d9bce9d9 1297{
74637406
AJ
1298 tcg_gen_mul_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
1299 cpu_gpr[rB(ctx->opcode)]);
1300 if (unlikely(Rc(ctx->opcode) != 0))
1301 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 1302}
74637406
AJ
1303/* mulldo mulldo. */
1304GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17);
d9bce9d9 1305#endif
74637406
AJ
1306
1307/* neg neg. nego nego. */
ec6469a3 1308static always_inline void gen_op_arith_neg (DisasContext *ctx, TCGv ret, TCGv arg1, int ov_check)
d9bce9d9 1309{
ec6469a3
AJ
1310 int l1 = gen_new_label();
1311 int l2 = gen_new_label();
a7812ae4 1312 TCGv t0 = tcg_temp_local_new();
d9bce9d9 1313#if defined(TARGET_PPC64)
74637406 1314 if (ctx->sf_mode) {
741a7444 1315 tcg_gen_mov_tl(t0, arg1);
ec6469a3
AJ
1316 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT64_MIN, l1);
1317 } else
1318#endif
1319 {
1320 tcg_gen_ext32s_tl(t0, arg1);
74637406
AJ
1321 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, INT32_MIN, l1);
1322 }
74637406
AJ
1323 tcg_gen_neg_tl(ret, arg1);
1324 if (ov_check) {
1325 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1326 }
1327 tcg_gen_br(l2);
1328 gen_set_label(l1);
ec6469a3 1329 tcg_gen_mov_tl(ret, t0);
74637406
AJ
1330 if (ov_check) {
1331 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
1332 }
1333 gen_set_label(l2);
ec6469a3 1334 tcg_temp_free(t0);
74637406
AJ
1335 if (unlikely(Rc(ctx->opcode) != 0))
1336 gen_set_Rc0(ctx, ret);
1337}
1338GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER)
d9bce9d9 1339{
ec6469a3 1340 gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0);
d9bce9d9 1341}
74637406 1342GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER)
79aceca5 1343{
ec6469a3 1344 gen_op_arith_neg(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 1);
79aceca5 1345}
74637406
AJ
1346
1347/* Common subf function */
1348static always_inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1, TCGv arg2,
1349 int add_ca, int compute_ca, int compute_ov)
79aceca5 1350{
74637406 1351 TCGv t0, t1;
76a66253 1352
74637406 1353 if ((!compute_ca && !compute_ov) ||
a7812ae4 1354 (!TCGV_EQUAL(ret, arg1) && !TCGV_EQUAL(ret, arg2))) {
74637406 1355 t0 = ret;
e864cabd 1356 } else {
a7812ae4 1357 t0 = tcg_temp_local_new();
d9bce9d9 1358 }
76a66253 1359
74637406 1360 if (add_ca) {
a7812ae4 1361 t1 = tcg_temp_local_new();
74637406
AJ
1362 tcg_gen_andi_tl(t1, cpu_xer, (1 << XER_CA));
1363 tcg_gen_shri_tl(t1, t1, XER_CA);
d9bce9d9 1364 }
79aceca5 1365
74637406
AJ
1366 if (compute_ca && compute_ov) {
1367 /* Start with XER CA and OV disabled, the most likely case */
1368 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~((1 << XER_CA) | (1 << XER_OV)));
1369 } else if (compute_ca) {
1370 /* Start with XER CA disabled, the most likely case */
1371 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
1372 } else if (compute_ov) {
1373 /* Start with XER OV disabled, the most likely case */
1374 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
1375 }
1376
1377 if (add_ca) {
1378 tcg_gen_not_tl(t0, arg1);
1379 tcg_gen_add_tl(t0, t0, arg2);
1380 gen_op_arith_compute_ca(ctx, t0, arg2, 0);
1381 tcg_gen_add_tl(t0, t0, t1);
1382 gen_op_arith_compute_ca(ctx, t0, t1, 0);
1383 tcg_temp_free(t1);
79aceca5 1384 } else {
74637406
AJ
1385 tcg_gen_sub_tl(t0, arg2, arg1);
1386 if (compute_ca) {
1387 gen_op_arith_compute_ca(ctx, t0, arg2, 1);
1388 }
1389 }
1390 if (compute_ov) {
1391 gen_op_arith_compute_ov(ctx, t0, arg1, arg2, 1);
1392 }
1393
1394 if (unlikely(Rc(ctx->opcode) != 0))
1395 gen_set_Rc0(ctx, t0);
1396
a7812ae4 1397 if (!TCGV_EQUAL(t0, ret)) {
74637406
AJ
1398 tcg_gen_mov_tl(ret, t0);
1399 tcg_temp_free(t0);
79aceca5 1400 }
79aceca5 1401}
74637406
AJ
1402/* Sub functions with Two operands functions */
1403#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
1404GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER) \
1405{ \
1406 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1407 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
1408 add_ca, compute_ca, compute_ov); \
1409}
1410/* Sub functions with one operand and one immediate */
1411#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
1412 add_ca, compute_ca, compute_ov) \
1413GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER) \
1414{ \
1415 TCGv t0 = tcg_const_local_tl(const_val); \
1416 gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
1417 cpu_gpr[rA(ctx->opcode)], t0, \
1418 add_ca, compute_ca, compute_ov); \
1419 tcg_temp_free(t0); \
1420}
1421/* subf subf. subfo subfo. */
1422GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
1423GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
1424/* subfc subfc. subfco subfco. */
1425GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
1426GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
1427/* subfe subfe. subfeo subfo. */
1428GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
1429GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
1430/* subfme subfme. subfmeo subfmeo. */
1431GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
1432GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
1433/* subfze subfze. subfzeo subfzeo.*/
1434GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
1435GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
79aceca5
FB
1436/* subfic */
1437GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1438{
74637406
AJ
1439 /* Start with XER CA and OV disabled, the most likely case */
1440 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
a7812ae4 1441 TCGv t0 = tcg_temp_local_new();
74637406
AJ
1442 TCGv t1 = tcg_const_local_tl(SIMM(ctx->opcode));
1443 tcg_gen_sub_tl(t0, t1, cpu_gpr[rA(ctx->opcode)]);
1444 gen_op_arith_compute_ca(ctx, t0, t1, 1);
1445 tcg_temp_free(t1);
1446 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
1447 tcg_temp_free(t0);
79aceca5
FB
1448}
1449
79aceca5 1450/*** Integer logical ***/
26d67362
AJ
1451#define GEN_LOGICAL2(name, tcg_op, opc, type) \
1452GEN_HANDLER(name, 0x1F, 0x1C, opc, 0x00000000, type) \
79aceca5 1453{ \
26d67362
AJ
1454 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], \
1455 cpu_gpr[rB(ctx->opcode)]); \
76a66253 1456 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1457 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5 1458}
79aceca5 1459
26d67362 1460#define GEN_LOGICAL1(name, tcg_op, opc, type) \
d9bce9d9 1461GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
79aceca5 1462{ \
26d67362 1463 tcg_op(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]); \
76a66253 1464 if (unlikely(Rc(ctx->opcode) != 0)) \
26d67362 1465 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]); \
79aceca5
FB
1466}
1467
1468/* and & and. */
26d67362 1469GEN_LOGICAL2(and, tcg_gen_and_tl, 0x00, PPC_INTEGER);
79aceca5 1470/* andc & andc. */
26d67362 1471GEN_LOGICAL2(andc, tcg_gen_andc_tl, 0x01, PPC_INTEGER);
79aceca5 1472/* andi. */
c7697e1f 1473GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
79aceca5 1474{
26d67362
AJ
1475 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode));
1476 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1477}
1478/* andis. */
c7697e1f 1479GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
79aceca5 1480{
26d67362
AJ
1481 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], UIMM(ctx->opcode) << 16);
1482 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5 1483}
79aceca5 1484/* cntlzw */
26d67362
AJ
1485GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER)
1486{
a7812ae4 1487 gen_helper_cntlzw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362 1488 if (unlikely(Rc(ctx->opcode) != 0))
2e31f5d3 1489 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
26d67362 1490}
79aceca5 1491/* eqv & eqv. */
26d67362 1492GEN_LOGICAL2(eqv, tcg_gen_eqv_tl, 0x08, PPC_INTEGER);
79aceca5 1493/* extsb & extsb. */
26d67362 1494GEN_LOGICAL1(extsb, tcg_gen_ext8s_tl, 0x1D, PPC_INTEGER);
79aceca5 1495/* extsh & extsh. */
26d67362 1496GEN_LOGICAL1(extsh, tcg_gen_ext16s_tl, 0x1C, PPC_INTEGER);
79aceca5 1497/* nand & nand. */
26d67362 1498GEN_LOGICAL2(nand, tcg_gen_nand_tl, 0x0E, PPC_INTEGER);
79aceca5 1499/* nor & nor. */
26d67362 1500GEN_LOGICAL2(nor, tcg_gen_nor_tl, 0x03, PPC_INTEGER);
79aceca5 1501/* or & or. */
9a64fbe4
FB
1502GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1503{
76a66253
JM
1504 int rs, ra, rb;
1505
1506 rs = rS(ctx->opcode);
1507 ra = rA(ctx->opcode);
1508 rb = rB(ctx->opcode);
1509 /* Optimisation for mr. ri case */
1510 if (rs != ra || rs != rb) {
26d67362
AJ
1511 if (rs != rb)
1512 tcg_gen_or_tl(cpu_gpr[ra], cpu_gpr[rs], cpu_gpr[rb]);
1513 else
1514 tcg_gen_mov_tl(cpu_gpr[ra], cpu_gpr[rs]);
76a66253 1515 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1516 gen_set_Rc0(ctx, cpu_gpr[ra]);
76a66253 1517 } else if (unlikely(Rc(ctx->opcode) != 0)) {
26d67362 1518 gen_set_Rc0(ctx, cpu_gpr[rs]);
c80f84e3
JM
1519#if defined(TARGET_PPC64)
1520 } else {
26d67362
AJ
1521 int prio = 0;
1522
c80f84e3
JM
1523 switch (rs) {
1524 case 1:
1525 /* Set process priority to low */
26d67362 1526 prio = 2;
c80f84e3
JM
1527 break;
1528 case 6:
1529 /* Set process priority to medium-low */
26d67362 1530 prio = 3;
c80f84e3
JM
1531 break;
1532 case 2:
1533 /* Set process priority to normal */
26d67362 1534 prio = 4;
c80f84e3 1535 break;
be147d08
JM
1536#if !defined(CONFIG_USER_ONLY)
1537 case 31:
1538 if (ctx->supervisor > 0) {
1539 /* Set process priority to very low */
26d67362 1540 prio = 1;
be147d08
JM
1541 }
1542 break;
1543 case 5:
1544 if (ctx->supervisor > 0) {
1545 /* Set process priority to medium-hight */
26d67362 1546 prio = 5;
be147d08
JM
1547 }
1548 break;
1549 case 3:
1550 if (ctx->supervisor > 0) {
1551 /* Set process priority to high */
26d67362 1552 prio = 6;
be147d08
JM
1553 }
1554 break;
be147d08
JM
1555 case 7:
1556 if (ctx->supervisor > 1) {
1557 /* Set process priority to very high */
26d67362 1558 prio = 7;
be147d08
JM
1559 }
1560 break;
be147d08 1561#endif
c80f84e3
JM
1562 default:
1563 /* nop */
1564 break;
1565 }
26d67362 1566 if (prio) {
a7812ae4 1567 TCGv t0 = tcg_temp_new();
54cdcae6 1568 gen_load_spr(t0, SPR_PPR);
ea363694
AJ
1569 tcg_gen_andi_tl(t0, t0, ~0x001C000000000000ULL);
1570 tcg_gen_ori_tl(t0, t0, ((uint64_t)prio) << 50);
54cdcae6 1571 gen_store_spr(SPR_PPR, t0);
ea363694 1572 tcg_temp_free(t0);
26d67362 1573 }
c80f84e3 1574#endif
9a64fbe4 1575 }
9a64fbe4 1576}
79aceca5 1577/* orc & orc. */
26d67362 1578GEN_LOGICAL2(orc, tcg_gen_orc_tl, 0x0C, PPC_INTEGER);
79aceca5 1579/* xor & xor. */
9a64fbe4
FB
1580GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1581{
9a64fbe4 1582 /* Optimisation for "set to zero" case */
26d67362 1583 if (rS(ctx->opcode) != rB(ctx->opcode))
312179c4 1584 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1585 else
1586 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
76a66253 1587 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1588 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
9a64fbe4 1589}
79aceca5
FB
1590/* ori */
1591GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1592{
76a66253 1593 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1594
9a64fbe4
FB
1595 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1596 /* NOP */
76a66253 1597 /* XXX: should handle special NOPs for POWER series */
9a64fbe4 1598 return;
76a66253 1599 }
26d67362 1600 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5
FB
1601}
1602/* oris */
1603GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1604{
76a66253 1605 target_ulong uimm = UIMM(ctx->opcode);
79aceca5 1606
9a64fbe4
FB
1607 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1608 /* NOP */
1609 return;
76a66253 1610 }
26d67362 1611 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5
FB
1612}
1613/* xori */
1614GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1615{
76a66253 1616 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1617
1618 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1619 /* NOP */
1620 return;
1621 }
26d67362 1622 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm);
79aceca5 1623}
79aceca5
FB
1624/* xoris */
1625GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1626{
76a66253 1627 target_ulong uimm = UIMM(ctx->opcode);
9a64fbe4
FB
1628
1629 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1630 /* NOP */
1631 return;
1632 }
26d67362 1633 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], uimm << 16);
79aceca5 1634}
d9bce9d9 1635/* popcntb : PowerPC 2.03 specification */
05332d70 1636GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
d9bce9d9 1637{
d9bce9d9
JM
1638#if defined(TARGET_PPC64)
1639 if (ctx->sf_mode)
a7812ae4 1640 gen_helper_popcntb_64(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9
JM
1641 else
1642#endif
a7812ae4 1643 gen_helper_popcntb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
d9bce9d9
JM
1644}
1645
1646#if defined(TARGET_PPC64)
1647/* extsw & extsw. */
26d67362 1648GEN_LOGICAL1(extsw, tcg_gen_ext32s_tl, 0x1E, PPC_64B);
d9bce9d9 1649/* cntlzd */
26d67362
AJ
1650GEN_HANDLER(cntlzd, 0x1F, 0x1A, 0x01, 0x00000000, PPC_64B)
1651{
a7812ae4 1652 gen_helper_cntlzd(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
26d67362
AJ
1653 if (unlikely(Rc(ctx->opcode) != 0))
1654 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1655}
d9bce9d9
JM
1656#endif
1657
79aceca5
FB
1658/*** Integer rotate ***/
1659/* rlwimi & rlwimi. */
1660GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1661{
76a66253 1662 uint32_t mb, me, sh;
79aceca5
FB
1663
1664 mb = MB(ctx->opcode);
1665 me = ME(ctx->opcode);
76a66253 1666 sh = SH(ctx->opcode);
d03ef511
AJ
1667 if (likely(sh == 0 && mb == 0 && me == 31)) {
1668 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1669 } else {
d03ef511 1670 target_ulong mask;
a7812ae4
PB
1671 TCGv t1;
1672 TCGv t0 = tcg_temp_new();
54843a58 1673#if defined(TARGET_PPC64)
a7812ae4
PB
1674 TCGv_i32 t2 = tcg_temp_new_i32();
1675 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rS(ctx->opcode)]);
1676 tcg_gen_rotli_i32(t2, t2, sh);
1677 tcg_gen_extu_i32_i64(t0, t2);
1678 tcg_temp_free_i32(t2);
54843a58
AJ
1679#else
1680 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1681#endif
76a66253 1682#if defined(TARGET_PPC64)
d03ef511
AJ
1683 mb += 32;
1684 me += 32;
76a66253 1685#endif
d03ef511 1686 mask = MASK(mb, me);
a7812ae4 1687 t1 = tcg_temp_new();
d03ef511
AJ
1688 tcg_gen_andi_tl(t0, t0, mask);
1689 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1690 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1691 tcg_temp_free(t0);
1692 tcg_temp_free(t1);
1693 }
76a66253 1694 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1695 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1696}
1697/* rlwinm & rlwinm. */
1698GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1699{
1700 uint32_t mb, me, sh;
3b46e624 1701
79aceca5
FB
1702 sh = SH(ctx->opcode);
1703 mb = MB(ctx->opcode);
1704 me = ME(ctx->opcode);
d03ef511
AJ
1705
1706 if (likely(mb == 0 && me == (31 - sh))) {
1707 if (likely(sh == 0)) {
1708 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1709 } else {
a7812ae4 1710 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1711 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1712 tcg_gen_shli_tl(t0, t0, sh);
1713 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1714 tcg_temp_free(t0);
79aceca5 1715 }
d03ef511 1716 } else if (likely(sh != 0 && me == 31 && sh == (32 - mb))) {
a7812ae4 1717 TCGv t0 = tcg_temp_new();
d03ef511
AJ
1718 tcg_gen_ext32u_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1719 tcg_gen_shri_tl(t0, t0, mb);
1720 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], t0);
1721 tcg_temp_free(t0);
1722 } else {
a7812ae4 1723 TCGv t0 = tcg_temp_new();
54843a58 1724#if defined(TARGET_PPC64)
a7812ae4 1725 TCGv_i32 t1 = tcg_temp_new_i32();
54843a58
AJ
1726 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1727 tcg_gen_rotli_i32(t1, t1, sh);
1728 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4 1729 tcg_temp_free_i32(t1);
54843a58
AJ
1730#else
1731 tcg_gen_rotli_i32(t0, cpu_gpr[rS(ctx->opcode)], sh);
1732#endif
76a66253 1733#if defined(TARGET_PPC64)
d03ef511
AJ
1734 mb += 32;
1735 me += 32;
76a66253 1736#endif
d03ef511
AJ
1737 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1738 tcg_temp_free(t0);
1739 }
76a66253 1740 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1741 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1742}
1743/* rlwnm & rlwnm. */
1744GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1745{
1746 uint32_t mb, me;
54843a58
AJ
1747 TCGv t0;
1748#if defined(TARGET_PPC64)
a7812ae4 1749 TCGv_i32 t1, t2;
54843a58 1750#endif
79aceca5
FB
1751
1752 mb = MB(ctx->opcode);
1753 me = ME(ctx->opcode);
a7812ae4 1754 t0 = tcg_temp_new();
d03ef511 1755 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1f);
54843a58 1756#if defined(TARGET_PPC64)
a7812ae4
PB
1757 t1 = tcg_temp_new_i32();
1758 t2 = tcg_temp_new_i32();
54843a58
AJ
1759 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rS(ctx->opcode)]);
1760 tcg_gen_trunc_i64_i32(t2, t0);
1761 tcg_gen_rotl_i32(t1, t1, t2);
1762 tcg_gen_extu_i32_i64(t0, t1);
a7812ae4
PB
1763 tcg_temp_free_i32(t1);
1764 tcg_temp_free_i32(t2);
54843a58
AJ
1765#else
1766 tcg_gen_rotl_i32(t0, cpu_gpr[rS(ctx->opcode)], t0);
1767#endif
76a66253
JM
1768 if (unlikely(mb != 0 || me != 31)) {
1769#if defined(TARGET_PPC64)
1770 mb += 32;
1771 me += 32;
1772#endif
54843a58 1773 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
d03ef511 1774 } else {
54843a58 1775 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
79aceca5 1776 }
54843a58 1777 tcg_temp_free(t0);
76a66253 1778 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1779 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1780}
1781
d9bce9d9
JM
1782#if defined(TARGET_PPC64)
1783#define GEN_PPC64_R2(name, opc1, opc2) \
c7697e1f 1784GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
d9bce9d9
JM
1785{ \
1786 gen_##name(ctx, 0); \
1787} \
c7697e1f
JM
1788GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1789 PPC_64B) \
d9bce9d9
JM
1790{ \
1791 gen_##name(ctx, 1); \
1792}
1793#define GEN_PPC64_R4(name, opc1, opc2) \
c7697e1f 1794GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
d9bce9d9
JM
1795{ \
1796 gen_##name(ctx, 0, 0); \
1797} \
c7697e1f
JM
1798GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
1799 PPC_64B) \
d9bce9d9
JM
1800{ \
1801 gen_##name(ctx, 0, 1); \
1802} \
c7697e1f
JM
1803GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1804 PPC_64B) \
d9bce9d9
JM
1805{ \
1806 gen_##name(ctx, 1, 0); \
1807} \
c7697e1f
JM
1808GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
1809 PPC_64B) \
d9bce9d9
JM
1810{ \
1811 gen_##name(ctx, 1, 1); \
1812}
51789c41 1813
b068d6a7
JM
1814static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1815 uint32_t me, uint32_t sh)
51789c41 1816{
d03ef511
AJ
1817 if (likely(sh != 0 && mb == 0 && me == (63 - sh))) {
1818 tcg_gen_shli_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
1819 } else if (likely(sh != 0 && me == 63 && sh == (64 - mb))) {
1820 tcg_gen_shri_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], mb);
1821 } else {
a7812ae4 1822 TCGv t0 = tcg_temp_new();
54843a58 1823 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
d03ef511 1824 if (likely(mb == 0 && me == 63)) {
54843a58 1825 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
d03ef511
AJ
1826 } else {
1827 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
51789c41 1828 }
d03ef511 1829 tcg_temp_free(t0);
51789c41 1830 }
51789c41 1831 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1832 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
51789c41 1833}
d9bce9d9 1834/* rldicl - rldicl. */
b068d6a7 1835static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
d9bce9d9 1836{
51789c41 1837 uint32_t sh, mb;
d9bce9d9 1838
9d53c753
JM
1839 sh = SH(ctx->opcode) | (shn << 5);
1840 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1841 gen_rldinm(ctx, mb, 63, sh);
d9bce9d9 1842}
51789c41 1843GEN_PPC64_R4(rldicl, 0x1E, 0x00);
d9bce9d9 1844/* rldicr - rldicr. */
b068d6a7 1845static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
d9bce9d9 1846{
51789c41 1847 uint32_t sh, me;
d9bce9d9 1848
9d53c753
JM
1849 sh = SH(ctx->opcode) | (shn << 5);
1850 me = MB(ctx->opcode) | (men << 5);
51789c41 1851 gen_rldinm(ctx, 0, me, sh);
d9bce9d9 1852}
51789c41 1853GEN_PPC64_R4(rldicr, 0x1E, 0x02);
d9bce9d9 1854/* rldic - rldic. */
b068d6a7 1855static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
d9bce9d9 1856{
51789c41 1857 uint32_t sh, mb;
d9bce9d9 1858
9d53c753
JM
1859 sh = SH(ctx->opcode) | (shn << 5);
1860 mb = MB(ctx->opcode) | (mbn << 5);
51789c41
JM
1861 gen_rldinm(ctx, mb, 63 - sh, sh);
1862}
1863GEN_PPC64_R4(rldic, 0x1E, 0x04);
1864
b068d6a7
JM
1865static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1866 uint32_t me)
51789c41 1867{
54843a58 1868 TCGv t0;
d03ef511
AJ
1869
1870 mb = MB(ctx->opcode);
1871 me = ME(ctx->opcode);
a7812ae4 1872 t0 = tcg_temp_new();
d03ef511 1873 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
54843a58 1874 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
51789c41 1875 if (unlikely(mb != 0 || me != 63)) {
54843a58
AJ
1876 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], t0, MASK(mb, me));
1877 } else {
1878 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
1879 }
1880 tcg_temp_free(t0);
51789c41 1881 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1882 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1883}
51789c41 1884
d9bce9d9 1885/* rldcl - rldcl. */
b068d6a7 1886static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
d9bce9d9 1887{
51789c41 1888 uint32_t mb;
d9bce9d9 1889
9d53c753 1890 mb = MB(ctx->opcode) | (mbn << 5);
51789c41 1891 gen_rldnm(ctx, mb, 63);
d9bce9d9 1892}
36081602 1893GEN_PPC64_R2(rldcl, 0x1E, 0x08);
d9bce9d9 1894/* rldcr - rldcr. */
b068d6a7 1895static always_inline void gen_rldcr (DisasContext *ctx, int men)
d9bce9d9 1896{
51789c41 1897 uint32_t me;
d9bce9d9 1898
9d53c753 1899 me = MB(ctx->opcode) | (men << 5);
51789c41 1900 gen_rldnm(ctx, 0, me);
d9bce9d9 1901}
36081602 1902GEN_PPC64_R2(rldcr, 0x1E, 0x09);
d9bce9d9 1903/* rldimi - rldimi. */
b068d6a7 1904static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
d9bce9d9 1905{
271a916e 1906 uint32_t sh, mb, me;
d9bce9d9 1907
9d53c753
JM
1908 sh = SH(ctx->opcode) | (shn << 5);
1909 mb = MB(ctx->opcode) | (mbn << 5);
271a916e 1910 me = 63 - sh;
d03ef511
AJ
1911 if (unlikely(sh == 0 && mb == 0)) {
1912 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
1913 } else {
1914 TCGv t0, t1;
1915 target_ulong mask;
1916
a7812ae4 1917 t0 = tcg_temp_new();
54843a58 1918 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
a7812ae4 1919 t1 = tcg_temp_new();
d03ef511
AJ
1920 mask = MASK(mb, me);
1921 tcg_gen_andi_tl(t0, t0, mask);
1922 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], ~mask);
1923 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
1924 tcg_temp_free(t0);
1925 tcg_temp_free(t1);
51789c41 1926 }
51789c41 1927 if (unlikely(Rc(ctx->opcode) != 0))
d03ef511 1928 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 1929}
36081602 1930GEN_PPC64_R4(rldimi, 0x1E, 0x06);
d9bce9d9
JM
1931#endif
1932
79aceca5
FB
1933/*** Integer shift ***/
1934/* slw & slw. */
26d67362
AJ
1935GEN_HANDLER(slw, 0x1F, 0x18, 0x00, 0x00000000, PPC_INTEGER)
1936{
fea0c503 1937 TCGv t0;
26d67362
AJ
1938 int l1, l2;
1939 l1 = gen_new_label();
1940 l2 = gen_new_label();
1941
a7812ae4 1942 t0 = tcg_temp_local_new();
0cfe58cd
AJ
1943 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
1944 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
26d67362
AJ
1945 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
1946 tcg_gen_br(l2);
1947 gen_set_label(l1);
fea0c503 1948 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
26d67362
AJ
1949 tcg_gen_ext32u_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
1950 gen_set_label(l2);
fea0c503 1951 tcg_temp_free(t0);
26d67362
AJ
1952 if (unlikely(Rc(ctx->opcode) != 0))
1953 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1954}
79aceca5 1955/* sraw & sraw. */
26d67362
AJ
1956GEN_HANDLER(sraw, 0x1F, 0x18, 0x18, 0x00000000, PPC_INTEGER)
1957{
a7812ae4
PB
1958 gen_helper_sraw(cpu_gpr[rA(ctx->opcode)],
1959 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
1960 if (unlikely(Rc(ctx->opcode) != 0))
1961 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
1962}
79aceca5
FB
1963/* srawi & srawi. */
1964GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1965{
26d67362
AJ
1966 int sh = SH(ctx->opcode);
1967 if (sh != 0) {
1968 int l1, l2;
fea0c503 1969 TCGv t0;
26d67362
AJ
1970 l1 = gen_new_label();
1971 l2 = gen_new_label();
a7812ae4 1972 t0 = tcg_temp_local_new();
fea0c503
AJ
1973 tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1974 tcg_gen_brcondi_tl(TCG_COND_GE, t0, 0, l1);
1975 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
1976 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
269f3e95 1977 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
26d67362
AJ
1978 tcg_gen_br(l2);
1979 gen_set_label(l1);
269f3e95 1980 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
26d67362 1981 gen_set_label(l2);
fea0c503
AJ
1982 tcg_gen_ext32s_tl(t0, cpu_gpr[rS(ctx->opcode)]);
1983 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], t0, sh);
1984 tcg_temp_free(t0);
26d67362
AJ
1985 } else {
1986 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
269f3e95 1987 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
d9bce9d9 1988 }
76a66253 1989 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 1990 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
79aceca5
FB
1991}
1992/* srw & srw. */
26d67362
AJ
1993GEN_HANDLER(srw, 0x1F, 0x18, 0x10, 0x00000000, PPC_INTEGER)
1994{
fea0c503 1995 TCGv t0, t1;
26d67362
AJ
1996 int l1, l2;
1997 l1 = gen_new_label();
1998 l2 = gen_new_label();
d9bce9d9 1999
a7812ae4 2000 t0 = tcg_temp_local_new();
0cfe58cd
AJ
2001 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x3f);
2002 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x20, l1);
26d67362
AJ
2003 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2004 tcg_gen_br(l2);
2005 gen_set_label(l1);
a7812ae4 2006 t1 = tcg_temp_new();
fea0c503
AJ
2007 tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
2008 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], t1, t0);
2009 tcg_temp_free(t1);
26d67362 2010 gen_set_label(l2);
fea0c503 2011 tcg_temp_free(t0);
26d67362
AJ
2012 if (unlikely(Rc(ctx->opcode) != 0))
2013 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2014}
d9bce9d9
JM
2015#if defined(TARGET_PPC64)
2016/* sld & sld. */
26d67362
AJ
2017GEN_HANDLER(sld, 0x1F, 0x1B, 0x00, 0x00000000, PPC_64B)
2018{
fea0c503 2019 TCGv t0;
26d67362
AJ
2020 int l1, l2;
2021 l1 = gen_new_label();
2022 l2 = gen_new_label();
2023
a7812ae4 2024 t0 = tcg_temp_local_new();
0cfe58cd
AJ
2025 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
2026 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
26d67362
AJ
2027 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2028 tcg_gen_br(l2);
2029 gen_set_label(l1);
fea0c503 2030 tcg_gen_shl_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
26d67362 2031 gen_set_label(l2);
fea0c503 2032 tcg_temp_free(t0);
26d67362
AJ
2033 if (unlikely(Rc(ctx->opcode) != 0))
2034 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2035}
d9bce9d9 2036/* srad & srad. */
26d67362
AJ
2037GEN_HANDLER(srad, 0x1F, 0x1A, 0x18, 0x00000000, PPC_64B)
2038{
a7812ae4
PB
2039 gen_helper_srad(cpu_gpr[rA(ctx->opcode)],
2040 cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
26d67362
AJ
2041 if (unlikely(Rc(ctx->opcode) != 0))
2042 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2043}
d9bce9d9 2044/* sradi & sradi. */
b068d6a7 2045static always_inline void gen_sradi (DisasContext *ctx, int n)
d9bce9d9 2046{
26d67362 2047 int sh = SH(ctx->opcode) + (n << 5);
d9bce9d9 2048 if (sh != 0) {
26d67362 2049 int l1, l2;
fea0c503 2050 TCGv t0;
26d67362
AJ
2051 l1 = gen_new_label();
2052 l2 = gen_new_label();
a7812ae4 2053 t0 = tcg_temp_local_new();
26d67362 2054 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
fea0c503
AJ
2055 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1ULL << sh) - 1);
2056 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
269f3e95 2057 tcg_gen_ori_tl(cpu_xer, cpu_xer, 1 << XER_CA);
26d67362
AJ
2058 tcg_gen_br(l2);
2059 gen_set_label(l1);
269f3e95 2060 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
26d67362 2061 gen_set_label(l2);
a9730017 2062 tcg_temp_free(t0);
26d67362
AJ
2063 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
2064 } else {
2065 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
269f3e95 2066 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
d9bce9d9 2067 }
d9bce9d9 2068 if (unlikely(Rc(ctx->opcode) != 0))
26d67362 2069 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
d9bce9d9 2070}
c7697e1f 2071GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
d9bce9d9
JM
2072{
2073 gen_sradi(ctx, 0);
2074}
c7697e1f 2075GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
d9bce9d9
JM
2076{
2077 gen_sradi(ctx, 1);
2078}
2079/* srd & srd. */
26d67362
AJ
2080GEN_HANDLER(srd, 0x1F, 0x1B, 0x10, 0x00000000, PPC_64B)
2081{
fea0c503 2082 TCGv t0;
26d67362
AJ
2083 int l1, l2;
2084 l1 = gen_new_label();
2085 l2 = gen_new_label();
2086
a7812ae4 2087 t0 = tcg_temp_local_new();
0cfe58cd
AJ
2088 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x7f);
2089 tcg_gen_brcondi_tl(TCG_COND_LT, t0, 0x40, l1);
26d67362
AJ
2090 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
2091 tcg_gen_br(l2);
2092 gen_set_label(l1);
fea0c503 2093 tcg_gen_shr_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t0);
26d67362 2094 gen_set_label(l2);
fea0c503 2095 tcg_temp_free(t0);
26d67362
AJ
2096 if (unlikely(Rc(ctx->opcode) != 0))
2097 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
2098}
d9bce9d9 2099#endif
79aceca5
FB
2100
2101/*** Floating-Point arithmetic ***/
7c58044c 2102#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
a750fc0b 2103GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
9a64fbe4 2104{ \
76a66253 2105 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 2106 GEN_EXCP_NO_FP(ctx); \
3cc62370
FB
2107 return; \
2108 } \
7c58044c 2109 gen_reset_fpstatus(); \
af12906f
AJ
2110 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2111 cpu_fpr[rC(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2112 if (isfloat) { \
af12906f 2113 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2114 } \
af12906f
AJ
2115 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], set_fprf, \
2116 Rc(ctx->opcode) != 0); \
9a64fbe4
FB
2117}
2118
7c58044c
JM
2119#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
2120_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
2121_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
9a64fbe4 2122
7c58044c
JM
2123#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
2124GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
9a64fbe4 2125{ \
76a66253 2126 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 2127 GEN_EXCP_NO_FP(ctx); \
3cc62370
FB
2128 return; \
2129 } \
7c58044c 2130 gen_reset_fpstatus(); \
af12906f
AJ
2131 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2132 cpu_fpr[rB(ctx->opcode)]); \
4ecc3190 2133 if (isfloat) { \
af12906f 2134 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2135 } \
af12906f
AJ
2136 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2137 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2138}
7c58044c
JM
2139#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
2140_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2141_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2142
7c58044c
JM
2143#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
2144GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
9a64fbe4 2145{ \
76a66253 2146 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 2147 GEN_EXCP_NO_FP(ctx); \
3cc62370
FB
2148 return; \
2149 } \
7c58044c 2150 gen_reset_fpstatus(); \
af12906f
AJ
2151 gen_helper_f##op(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rA(ctx->opcode)], \
2152 cpu_fpr[rC(ctx->opcode)]); \
4ecc3190 2153 if (isfloat) { \
af12906f 2154 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]); \
4ecc3190 2155 } \
af12906f
AJ
2156 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2157 set_fprf, Rc(ctx->opcode) != 0); \
9a64fbe4 2158}
7c58044c
JM
2159#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
2160_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
2161_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
9a64fbe4 2162
7c58044c 2163#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
a750fc0b 2164GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
9a64fbe4 2165{ \
76a66253 2166 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 2167 GEN_EXCP_NO_FP(ctx); \
3cc62370
FB
2168 return; \
2169 } \
7c58044c 2170 gen_reset_fpstatus(); \
af12906f
AJ
2171 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2172 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2173 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2174}
2175
7c58044c 2176#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
a750fc0b 2177GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
9a64fbe4 2178{ \
76a66253 2179 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 2180 GEN_EXCP_NO_FP(ctx); \
3cc62370
FB
2181 return; \
2182 } \
7c58044c 2183 gen_reset_fpstatus(); \
af12906f
AJ
2184 gen_helper_f##name(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]); \
2185 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], \
2186 set_fprf, Rc(ctx->opcode) != 0); \
79aceca5
FB
2187}
2188
9a64fbe4 2189/* fadd - fadds */
7c58044c 2190GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2191/* fdiv - fdivs */
7c58044c 2192GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
4ecc3190 2193/* fmul - fmuls */
7c58044c 2194GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
79aceca5 2195
d7e4b87e 2196/* fre */
7c58044c 2197GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
d7e4b87e 2198
a750fc0b 2199/* fres */
7c58044c 2200GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
79aceca5 2201
a750fc0b 2202/* frsqrte */
7c58044c
JM
2203GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
2204
2205/* frsqrtes */
af12906f 2206GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES)
7c58044c 2207{
af12906f
AJ
2208 if (unlikely(!ctx->fpu_enabled)) {
2209 GEN_EXCP_NO_FP(ctx);
2210 return;
2211 }
2212 gen_reset_fpstatus();
2213 gen_helper_frsqrte(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2214 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2215 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
7c58044c 2216}
79aceca5 2217
a750fc0b 2218/* fsel */
7c58044c 2219_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
4ecc3190 2220/* fsub - fsubs */
7c58044c 2221GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
79aceca5
FB
2222/* Optional: */
2223/* fsqrt */
a750fc0b 2224GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
c7d344af 2225{
76a66253 2226 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2227 GEN_EXCP_NO_FP(ctx);
c7d344af
FB
2228 return;
2229 }
7c58044c 2230 gen_reset_fpstatus();
af12906f
AJ
2231 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2232 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
c7d344af 2233}
79aceca5 2234
a750fc0b 2235GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
79aceca5 2236{
76a66253 2237 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2238 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2239 return;
2240 }
7c58044c 2241 gen_reset_fpstatus();
af12906f
AJ
2242 gen_helper_fsqrt(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2243 gen_helper_frsp(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rD(ctx->opcode)]);
2244 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 1, Rc(ctx->opcode) != 0);
79aceca5
FB
2245}
2246
2247/*** Floating-Point multiply-and-add ***/
4ecc3190 2248/* fmadd - fmadds */
7c58044c 2249GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
4ecc3190 2250/* fmsub - fmsubs */
7c58044c 2251GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
4ecc3190 2252/* fnmadd - fnmadds */
7c58044c 2253GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
4ecc3190 2254/* fnmsub - fnmsubs */
7c58044c 2255GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
79aceca5
FB
2256
2257/*** Floating-Point round & convert ***/
2258/* fctiw */
7c58044c 2259GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
79aceca5 2260/* fctiwz */
7c58044c 2261GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
79aceca5 2262/* frsp */
7c58044c 2263GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
426613db
JM
2264#if defined(TARGET_PPC64)
2265/* fcfid */
7c58044c 2266GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
426613db 2267/* fctid */
7c58044c 2268GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
426613db 2269/* fctidz */
7c58044c 2270GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
426613db 2271#endif
79aceca5 2272
d7e4b87e 2273/* frin */
7c58044c 2274GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
d7e4b87e 2275/* friz */
7c58044c 2276GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
d7e4b87e 2277/* frip */
7c58044c 2278GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
d7e4b87e 2279/* frim */
7c58044c 2280GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
d7e4b87e 2281
79aceca5
FB
2282/*** Floating-Point compare ***/
2283/* fcmpo */
76a66253 2284GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
79aceca5 2285{
76a66253 2286 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2287 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2288 return;
2289 }
7c58044c 2290 gen_reset_fpstatus();
af12906f
AJ
2291 gen_helper_fcmpo(cpu_crf[crfD(ctx->opcode)],
2292 cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2293 gen_helper_float_check_status();
79aceca5
FB
2294}
2295
2296/* fcmpu */
76a66253 2297GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
79aceca5 2298{
76a66253 2299 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2300 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2301 return;
2302 }
7c58044c 2303 gen_reset_fpstatus();
af12906f
AJ
2304 gen_helper_fcmpu(cpu_crf[crfD(ctx->opcode)],
2305 cpu_fpr[rA(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2306 gen_helper_float_check_status();
79aceca5
FB
2307}
2308
9a64fbe4
FB
2309/*** Floating-point move ***/
2310/* fabs */
7c58044c
JM
2311/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
2312GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
9a64fbe4
FB
2313
2314/* fmr - fmr. */
7c58044c 2315/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
9a64fbe4
FB
2316GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
2317{
76a66253 2318 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2319 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2320 return;
2321 }
af12906f
AJ
2322 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpr[rB(ctx->opcode)]);
2323 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
9a64fbe4
FB
2324}
2325
2326/* fnabs */
7c58044c
JM
2327/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
2328GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
9a64fbe4 2329/* fneg */
7c58044c
JM
2330/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
2331GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
9a64fbe4 2332
79aceca5
FB
2333/*** Floating-Point status & ctrl register ***/
2334/* mcrfs */
2335GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
2336{
7c58044c
JM
2337 int bfa;
2338
76a66253 2339 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2340 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2341 return;
2342 }
7c58044c
JM
2343 gen_optimize_fprf();
2344 bfa = 4 * (7 - crfS(ctx->opcode));
e1571908
AJ
2345 tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_fpscr, bfa);
2346 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], 0xf);
af12906f 2347 tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(0xF << bfa));
79aceca5
FB
2348}
2349
2350/* mffs */
2351GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
2352{
76a66253 2353 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2354 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2355 return;
2356 }
7c58044c
JM
2357 gen_optimize_fprf();
2358 gen_reset_fpstatus();
af12906f
AJ
2359 tcg_gen_extu_i32_i64(cpu_fpr[rD(ctx->opcode)], cpu_fpscr);
2360 gen_compute_fprf(cpu_fpr[rD(ctx->opcode)], 0, Rc(ctx->opcode) != 0);
79aceca5
FB
2361}
2362
2363/* mtfsb0 */
2364GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
2365{
fb0eaffc 2366 uint8_t crb;
3b46e624 2367
76a66253 2368 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2369 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2370 return;
2371 }
7c58044c
JM
2372 crb = 32 - (crbD(ctx->opcode) >> 2);
2373 gen_optimize_fprf();
2374 gen_reset_fpstatus();
2375 if (likely(crb != 30 && crb != 29))
af12906f 2376 tcg_gen_andi_i32(cpu_fpscr, cpu_fpscr, ~(1 << crb));
7c58044c 2377 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2378 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c 2379 }
79aceca5
FB
2380}
2381
2382/* mtfsb1 */
2383GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2384{
fb0eaffc 2385 uint8_t crb;
3b46e624 2386
76a66253 2387 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2388 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2389 return;
2390 }
7c58044c
JM
2391 crb = 32 - (crbD(ctx->opcode) >> 2);
2392 gen_optimize_fprf();
2393 gen_reset_fpstatus();
2394 /* XXX: we pretend we can only do IEEE floating-point computations */
af12906f 2395 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
0f2f39c2 2396 TCGv_i32 t0 = tcg_const_i32(crb);
af12906f 2397 gen_helper_fpscr_setbit(t0);
0f2f39c2 2398 tcg_temp_free_i32(t0);
af12906f 2399 }
7c58044c 2400 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2401 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2402 }
2403 /* We can raise a differed exception */
af12906f 2404 gen_helper_float_check_status();
79aceca5
FB
2405}
2406
2407/* mtfsf */
2408GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2409{
0f2f39c2 2410 TCGv_i32 t0;
af12906f 2411
76a66253 2412 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2413 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2414 return;
2415 }
7c58044c 2416 gen_optimize_fprf();
7c58044c 2417 gen_reset_fpstatus();
af12906f
AJ
2418 t0 = tcg_const_i32(FM(ctx->opcode));
2419 gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
0f2f39c2 2420 tcg_temp_free_i32(t0);
7c58044c 2421 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2422 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2423 }
2424 /* We can raise a differed exception */
af12906f 2425 gen_helper_float_check_status();
79aceca5
FB
2426}
2427
2428/* mtfsfi */
2429GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2430{
7c58044c 2431 int bf, sh;
0f2f39c2
AJ
2432 TCGv_i64 t0;
2433 TCGv_i32 t1;
7c58044c 2434
76a66253 2435 if (unlikely(!ctx->fpu_enabled)) {
e1833e1f 2436 GEN_EXCP_NO_FP(ctx);
3cc62370
FB
2437 return;
2438 }
7c58044c
JM
2439 bf = crbD(ctx->opcode) >> 2;
2440 sh = 7 - bf;
2441 gen_optimize_fprf();
7c58044c 2442 gen_reset_fpstatus();
0f2f39c2 2443 t0 = tcg_const_i64(FPIMM(ctx->opcode) << (4 * sh));
af12906f
AJ
2444 t1 = tcg_const_i32(1 << sh);
2445 gen_helper_store_fpscr(t0, t1);
0f2f39c2
AJ
2446 tcg_temp_free_i64(t0);
2447 tcg_temp_free_i32(t1);
7c58044c 2448 if (unlikely(Rc(ctx->opcode) != 0)) {
e1571908 2449 tcg_gen_shri_i32(cpu_crf[1], cpu_fpscr, FPSCR_OX);
7c58044c
JM
2450 }
2451 /* We can raise a differed exception */
af12906f 2452 gen_helper_float_check_status();
79aceca5
FB
2453}
2454
76a66253
JM
2455/*** Addressing modes ***/
2456/* Register indirect with immediate index : EA = (rA|0) + SIMM */
e2be8d8d
AJ
2457static always_inline void gen_addr_imm_index (TCGv EA,
2458 DisasContext *ctx,
b068d6a7 2459 target_long maskl)
76a66253
JM
2460{
2461 target_long simm = SIMM(ctx->opcode);
2462
be147d08 2463 simm &= ~maskl;
e2be8d8d
AJ
2464 if (rA(ctx->opcode) == 0)
2465 tcg_gen_movi_tl(EA, simm);
2466 else if (likely(simm != 0))
2467 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], simm);
2468 else
2469 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
2470}
2471
e2be8d8d
AJ
2472static always_inline void gen_addr_reg_index (TCGv EA,
2473 DisasContext *ctx)
76a66253 2474{
e2be8d8d
AJ
2475 if (rA(ctx->opcode) == 0)
2476 tcg_gen_mov_tl(EA, cpu_gpr[rB(ctx->opcode)]);
2477 else
2478 tcg_gen_add_tl(EA, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
2479}
2480
e2be8d8d
AJ
2481static always_inline void gen_addr_register (TCGv EA,
2482 DisasContext *ctx)
76a66253 2483{
e2be8d8d
AJ
2484 if (rA(ctx->opcode) == 0)
2485 tcg_gen_movi_tl(EA, 0);
2486 else
2487 tcg_gen_mov_tl(EA, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
2488}
2489
cf360a32
AJ
2490static always_inline void gen_check_align (DisasContext *ctx, TCGv EA, int mask)
2491{
2492 int l1 = gen_new_label();
2493 TCGv t0 = tcg_temp_new();
2494 TCGv_i32 t1, t2;
2495 /* NIP cannot be restored if the memory exception comes from an helper */
2496 gen_update_nip(ctx, ctx->nip - 4);
2497 tcg_gen_andi_tl(t0, EA, mask);
2498 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
2499 t1 = tcg_const_i32(POWERPC_EXCP_ALIGN);
2500 t2 = tcg_const_i32(0);
2501 gen_helper_raise_exception_err(t1, t2);
2502 tcg_temp_free_i32(t1);
2503 tcg_temp_free_i32(t2);
2504 gen_set_label(l1);
2505 tcg_temp_free(t0);
2506}
2507
7863667f 2508/*** Integer load ***/
b61f2753
AJ
2509#if defined(TARGET_PPC64)
2510#define GEN_QEMU_LD_PPC64(width) \
2511static always_inline void gen_qemu_ld##width##_ppc64(TCGv t0, TCGv t1, int flags)\
2512{ \
2513 if (likely(flags & 2)) \
2514 tcg_gen_qemu_ld##width(t0, t1, flags >> 2); \
2515 else { \
a7812ae4 2516 TCGv addr = tcg_temp_new(); \
b61f2753
AJ
2517 tcg_gen_ext32u_tl(addr, t1); \
2518 tcg_gen_qemu_ld##width(t0, addr, flags >> 2); \
2519 tcg_temp_free(addr); \
2520 } \
2521}
2522GEN_QEMU_LD_PPC64(8u)
2523GEN_QEMU_LD_PPC64(8s)
2524GEN_QEMU_LD_PPC64(16u)
2525GEN_QEMU_LD_PPC64(16s)
2526GEN_QEMU_LD_PPC64(32u)
2527GEN_QEMU_LD_PPC64(32s)
2528GEN_QEMU_LD_PPC64(64)
2529
2530#define GEN_QEMU_ST_PPC64(width) \
2531static always_inline void gen_qemu_st##width##_ppc64(TCGv t0, TCGv t1, int flags)\
2532{ \
2533 if (likely(flags & 2)) \
2534 tcg_gen_qemu_st##width(t0, t1, flags >> 2); \
2535 else { \
a7812ae4 2536 TCGv addr = tcg_temp_new(); \
b61f2753
AJ
2537 tcg_gen_ext32u_tl(addr, t1); \
2538 tcg_gen_qemu_st##width(t0, addr, flags >> 2); \
2539 tcg_temp_free(addr); \
2540 } \
2541}
2542GEN_QEMU_ST_PPC64(8)
2543GEN_QEMU_ST_PPC64(16)
2544GEN_QEMU_ST_PPC64(32)
2545GEN_QEMU_ST_PPC64(64)
2546
ea363694 2547static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
b61f2753 2548{
ea363694 2549 gen_qemu_ld8u_ppc64(arg0, arg1, flags);
b61f2753
AJ
2550}
2551
ea363694 2552static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
b61f2753 2553{
ea363694 2554 gen_qemu_ld8s_ppc64(arg0, arg1, flags);
b61f2753
AJ
2555}
2556
ea363694 2557static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2558{
2559 if (unlikely(flags & 1)) {
a7812ae4 2560 TCGv_i32 t0;
ea363694 2561 gen_qemu_ld16u_ppc64(arg0, arg1, flags);
a7812ae4 2562 t0 = tcg_temp_new_i32();
ea363694
AJ
2563 tcg_gen_trunc_tl_i32(t0, arg0);
2564 tcg_gen_bswap16_i32(t0, t0);
2565 tcg_gen_extu_i32_tl(arg0, t0);
a7812ae4 2566 tcg_temp_free_i32(t0);
b61f2753 2567 } else
ea363694 2568 gen_qemu_ld16u_ppc64(arg0, arg1, flags);
b61f2753
AJ
2569}
2570
ea363694 2571static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2572{
2573 if (unlikely(flags & 1)) {
a7812ae4 2574 TCGv_i32 t0;
ea363694 2575 gen_qemu_ld16u_ppc64(arg0, arg1, flags);
a7812ae4 2576 t0 = tcg_temp_new_i32();
ea363694
AJ
2577 tcg_gen_trunc_tl_i32(t0, arg0);
2578 tcg_gen_bswap16_i32(t0, t0);
2579 tcg_gen_extu_i32_tl(arg0, t0);
2580 tcg_gen_ext16s_tl(arg0, arg0);
a7812ae4 2581 tcg_temp_free_i32(t0);
b61f2753 2582 } else
ea363694 2583 gen_qemu_ld16s_ppc64(arg0, arg1, flags);
b61f2753
AJ
2584}
2585
ea363694 2586static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2587{
2588 if (unlikely(flags & 1)) {
a7812ae4 2589 TCGv_i32 t0;
ea363694 2590 gen_qemu_ld32u_ppc64(arg0, arg1, flags);
a7812ae4 2591 t0 = tcg_temp_new_i32();
ea363694
AJ
2592 tcg_gen_trunc_tl_i32(t0, arg0);
2593 tcg_gen_bswap_i32(t0, t0);
2594 tcg_gen_extu_i32_tl(arg0, t0);
a7812ae4 2595 tcg_temp_free_i32(t0);
b61f2753 2596 } else
ea363694 2597 gen_qemu_ld32u_ppc64(arg0, arg1, flags);
b61f2753
AJ
2598}
2599
ea363694 2600static always_inline void gen_qemu_ld32s(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2601{
2602 if (unlikely(flags & 1)) {
a7812ae4 2603 TCGv_i32 t0;
ea363694 2604 gen_qemu_ld32u_ppc64(arg0, arg1, flags);
a7812ae4 2605 t0 = tcg_temp_new_i32();
ea363694
AJ
2606 tcg_gen_trunc_tl_i32(t0, arg0);
2607 tcg_gen_bswap_i32(t0, t0);
2608 tcg_gen_ext_i32_tl(arg0, t0);
a7812ae4 2609 tcg_temp_free_i32(t0);
b61f2753 2610 } else
ea363694 2611 gen_qemu_ld32s_ppc64(arg0, arg1, flags);
b61f2753
AJ
2612}
2613
ea363694 2614static always_inline void gen_qemu_ld64(TCGv arg0, TCGv arg1, int flags)
b61f2753 2615{
ea363694 2616 gen_qemu_ld64_ppc64(arg0, arg1, flags);
b61f2753 2617 if (unlikely(flags & 1))
ea363694 2618 tcg_gen_bswap_i64(arg0, arg0);
b61f2753
AJ
2619}
2620
ea363694 2621static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
b61f2753 2622{
ea363694 2623 gen_qemu_st8_ppc64(arg0, arg1, flags);
b61f2753
AJ
2624}
2625
ea363694 2626static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2627{
2628 if (unlikely(flags & 1)) {
a7812ae4
PB
2629 TCGv_i32 t0;
2630 TCGv_i64 t1;
2631 t0 = tcg_temp_new_i32();
ea363694
AJ
2632 tcg_gen_trunc_tl_i32(t0, arg0);
2633 tcg_gen_ext16u_i32(t0, t0);
2634 tcg_gen_bswap16_i32(t0, t0);
a7812ae4 2635 t1 = tcg_temp_new_i64();
ea363694 2636 tcg_gen_extu_i32_tl(t1, t0);
a7812ae4 2637 tcg_temp_free_i32(t0);
ea363694 2638 gen_qemu_st16_ppc64(t1, arg1, flags);
a7812ae4 2639 tcg_temp_free_i64(t1);
b61f2753 2640 } else
ea363694 2641 gen_qemu_st16_ppc64(arg0, arg1, flags);
b61f2753
AJ
2642}
2643
ea363694 2644static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2645{
2646 if (unlikely(flags & 1)) {
a7812ae4
PB
2647 TCGv_i32 t0;
2648 TCGv_i64 t1;
2649 t0 = tcg_temp_new_i32();
ea363694
AJ
2650 tcg_gen_trunc_tl_i32(t0, arg0);
2651 tcg_gen_bswap_i32(t0, t0);
a7812ae4 2652 t1 = tcg_temp_new_i64();
ea363694 2653 tcg_gen_extu_i32_tl(t1, t0);
a7812ae4 2654 tcg_temp_free_i32(t0);
ea363694 2655 gen_qemu_st32_ppc64(t1, arg1, flags);
a7812ae4 2656 tcg_temp_free_i64(t1);
b61f2753 2657 } else
ea363694 2658 gen_qemu_st32_ppc64(arg0, arg1, flags);
b61f2753
AJ
2659}
2660
ea363694 2661static always_inline void gen_qemu_st64(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2662{
2663 if (unlikely(flags & 1)) {
a7812ae4 2664 TCGv_i64 t0 = tcg_temp_new_i64();
ea363694
AJ
2665 tcg_gen_bswap_i64(t0, arg0);
2666 gen_qemu_st64_ppc64(t0, arg1, flags);
a7812ae4 2667 tcg_temp_free_i64(t0);
b61f2753 2668 } else
ea363694 2669 gen_qemu_st64_ppc64(arg0, arg1, flags);
b61f2753
AJ
2670}
2671
2672
2673#else /* defined(TARGET_PPC64) */
a0d7d5a7
AJ
2674#define GEN_QEMU_LD_PPC32(width) \
2675static always_inline void gen_qemu_ld##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \
2676{ \
2677 tcg_gen_qemu_ld##width(arg0, arg1, flags >> 1); \
b61f2753
AJ
2678}
2679GEN_QEMU_LD_PPC32(8u)
2680GEN_QEMU_LD_PPC32(8s)
2681GEN_QEMU_LD_PPC32(16u)
2682GEN_QEMU_LD_PPC32(16s)
2683GEN_QEMU_LD_PPC32(32u)
2684GEN_QEMU_LD_PPC32(32s)
a0d7d5a7
AJ
2685static always_inline void gen_qemu_ld64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags)
2686{
2687 tcg_gen_qemu_ld64(arg0, arg1, flags >> 1);
2688}
b61f2753 2689
a0d7d5a7
AJ
2690#define GEN_QEMU_ST_PPC32(width) \
2691static always_inline void gen_qemu_st##width##_ppc32(TCGv arg0, TCGv arg1, int flags) \
2692{ \
2693 tcg_gen_qemu_st##width(arg0, arg1, flags >> 1); \
b61f2753
AJ
2694}
2695GEN_QEMU_ST_PPC32(8)
2696GEN_QEMU_ST_PPC32(16)
2697GEN_QEMU_ST_PPC32(32)
a0d7d5a7
AJ
2698static always_inline void gen_qemu_st64_ppc32(TCGv_i64 arg0, TCGv arg1, int flags)
2699{
2700 tcg_gen_qemu_st64(arg0, arg1, flags >> 1);
2701}
b61f2753 2702
ea363694 2703static always_inline void gen_qemu_ld8u(TCGv arg0, TCGv arg1, int flags)
b61f2753 2704{
ea363694 2705 gen_qemu_ld8u_ppc32(arg0, arg1, flags >> 1);
b61f2753
AJ
2706}
2707
ea363694 2708static always_inline void gen_qemu_ld8s(TCGv arg0, TCGv arg1, int flags)
b61f2753 2709{
ea363694 2710 gen_qemu_ld8s_ppc32(arg0, arg1, flags >> 1);
b61f2753
AJ
2711}
2712
ea363694 2713static always_inline void gen_qemu_ld16u(TCGv arg0, TCGv arg1, int flags)
b61f2753 2714{
ea363694 2715 gen_qemu_ld16u_ppc32(arg0, arg1, flags >> 1);
b61f2753 2716 if (unlikely(flags & 1))
ea363694 2717 tcg_gen_bswap16_i32(arg0, arg0);
b61f2753
AJ
2718}
2719
ea363694 2720static always_inline void gen_qemu_ld16s(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2721{
2722 if (unlikely(flags & 1)) {
ea363694
AJ
2723 gen_qemu_ld16u_ppc32(arg0, arg1, flags);
2724 tcg_gen_bswap16_i32(arg0, arg0);
2725 tcg_gen_ext16s_i32(arg0, arg0);
b61f2753 2726 } else
ea363694 2727 gen_qemu_ld16s_ppc32(arg0, arg1, flags);
b61f2753
AJ
2728}
2729
ea363694 2730static always_inline void gen_qemu_ld32u(TCGv arg0, TCGv arg1, int flags)
b61f2753 2731{
ea363694 2732 gen_qemu_ld32u_ppc32(arg0, arg1, flags);
b61f2753 2733 if (unlikely(flags & 1))
ea363694 2734 tcg_gen_bswap_i32(arg0, arg0);
b61f2753
AJ
2735}
2736
a0d7d5a7
AJ
2737static always_inline void gen_qemu_ld64(TCGv_i64 arg0, TCGv arg1, int flags)
2738{
2739 gen_qemu_ld64_ppc32(arg0, arg1, flags);
2740 if (unlikely(flags & 1))
2741 tcg_gen_bswap_i64(arg0, arg0);
2742}
2743
ea363694 2744static always_inline void gen_qemu_st8(TCGv arg0, TCGv arg1, int flags)
b61f2753 2745{
e32ad5c2 2746 gen_qemu_st8_ppc32(arg0, arg1, flags);
b61f2753
AJ
2747}
2748
ea363694 2749static always_inline void gen_qemu_st16(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2750{
2751 if (unlikely(flags & 1)) {
a7812ae4 2752 TCGv_i32 temp = tcg_temp_new_i32();
ea363694 2753 tcg_gen_ext16u_i32(temp, arg0);
b61f2753 2754 tcg_gen_bswap16_i32(temp, temp);
e32ad5c2 2755 gen_qemu_st16_ppc32(temp, arg1, flags);
a7812ae4 2756 tcg_temp_free_i32(temp);
b61f2753 2757 } else
e32ad5c2 2758 gen_qemu_st16_ppc32(arg0, arg1, flags);
b61f2753
AJ
2759}
2760
ea363694 2761static always_inline void gen_qemu_st32(TCGv arg0, TCGv arg1, int flags)
b61f2753
AJ
2762{
2763 if (unlikely(flags & 1)) {
a7812ae4 2764 TCGv_i32 temp = tcg_temp_new_i32();
ea363694 2765 tcg_gen_bswap_i32(temp, arg0);
e32ad5c2 2766 gen_qemu_st32_ppc32(temp, arg1, flags);
a7812ae4 2767 tcg_temp_free_i32(temp);
b61f2753 2768 } else
e32ad5c2 2769 gen_qemu_st32_ppc32(arg0, arg1, flags);
b61f2753
AJ
2770}
2771
a0d7d5a7
AJ
2772static always_inline void gen_qemu_st64(TCGv_i64 arg0, TCGv arg1, int flags)
2773{
2774 if (unlikely(flags & 1)) {
2775 TCGv_i64 temp = tcg_temp_new_i64();
2776 tcg_gen_bswap_i64(temp, arg0);
2777 gen_qemu_st64_ppc32(temp, arg1, flags);
2778 tcg_temp_free_i64(temp);
2779 } else
2780 gen_qemu_st64_ppc32(arg0, arg1, flags);
2781}
b61f2753
AJ
2782#endif
2783
0c8aacd4
AJ
2784#define GEN_LD(name, ldop, opc, type) \
2785GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 2786{ \
0c8aacd4 2787 TCGv EA = tcg_temp_new(); \
a7859e89 2788 gen_set_access_type(ACCESS_INT); \
b61f2753 2789 gen_addr_imm_index(EA, ctx, 0); \
0c8aacd4 2790 gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753 2791 tcg_temp_free(EA); \
79aceca5
FB
2792}
2793
0c8aacd4
AJ
2794#define GEN_LDU(name, ldop, opc, type) \
2795GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 2796{ \
b61f2753 2797 TCGv EA; \
76a66253
JM
2798 if (unlikely(rA(ctx->opcode) == 0 || \
2799 rA(ctx->opcode) == rD(ctx->opcode))) { \
e1833e1f 2800 GEN_EXCP_INVAL(ctx); \
9fddaa0c 2801 return; \
9a64fbe4 2802 } \
0c8aacd4 2803 EA = tcg_temp_new(); \
a7859e89 2804 gen_set_access_type(ACCESS_INT); \
9d53c753 2805 if (type == PPC_64B) \
b61f2753 2806 gen_addr_imm_index(EA, ctx, 0x03); \
9d53c753 2807 else \
b61f2753 2808 gen_addr_imm_index(EA, ctx, 0); \
0c8aacd4 2809 gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753
AJ
2810 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2811 tcg_temp_free(EA); \
79aceca5
FB
2812}
2813
0c8aacd4
AJ
2814#define GEN_LDUX(name, ldop, opc2, opc3, type) \
2815GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 2816{ \
b61f2753 2817 TCGv EA; \
76a66253
JM
2818 if (unlikely(rA(ctx->opcode) == 0 || \
2819 rA(ctx->opcode) == rD(ctx->opcode))) { \
e1833e1f 2820 GEN_EXCP_INVAL(ctx); \
9fddaa0c 2821 return; \
9a64fbe4 2822 } \
0c8aacd4 2823 EA = tcg_temp_new(); \
a7859e89 2824 gen_set_access_type(ACCESS_INT); \
b61f2753 2825 gen_addr_reg_index(EA, ctx); \
0c8aacd4 2826 gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753
AJ
2827 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2828 tcg_temp_free(EA); \
79aceca5
FB
2829}
2830
0c8aacd4
AJ
2831#define GEN_LDX(name, ldop, opc2, opc3, type) \
2832GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 2833{ \
0c8aacd4 2834 TCGv EA = tcg_temp_new(); \
a7859e89 2835 gen_set_access_type(ACCESS_INT); \
b61f2753 2836 gen_addr_reg_index(EA, ctx); \
0c8aacd4 2837 gen_qemu_##ldop(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753 2838 tcg_temp_free(EA); \
79aceca5
FB
2839}
2840
0c8aacd4
AJ
2841#define GEN_LDS(name, ldop, op, type) \
2842GEN_LD(name, ldop, op | 0x20, type); \
2843GEN_LDU(name, ldop, op | 0x21, type); \
2844GEN_LDUX(name, ldop, 0x17, op | 0x01, type); \
2845GEN_LDX(name, ldop, 0x17, op | 0x00, type)
79aceca5
FB
2846
2847/* lbz lbzu lbzux lbzx */
0c8aacd4 2848GEN_LDS(lbz, ld8u, 0x02, PPC_INTEGER);
79aceca5 2849/* lha lhau lhaux lhax */
0c8aacd4 2850GEN_LDS(lha, ld16s, 0x0A, PPC_INTEGER);
79aceca5 2851/* lhz lhzu lhzux lhzx */
0c8aacd4 2852GEN_LDS(lhz, ld16u, 0x08, PPC_INTEGER);
79aceca5 2853/* lwz lwzu lwzux lwzx */
0c8aacd4 2854GEN_LDS(lwz, ld32u, 0x00, PPC_INTEGER);
d9bce9d9 2855#if defined(TARGET_PPC64)
d9bce9d9 2856/* lwaux */
0c8aacd4 2857GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B);
d9bce9d9 2858/* lwax */
0c8aacd4 2859GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B);
d9bce9d9 2860/* ldux */
0c8aacd4 2861GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B);
d9bce9d9 2862/* ldx */
0c8aacd4 2863GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B);
d9bce9d9
JM
2864GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2865{
b61f2753 2866 TCGv EA;
d9bce9d9
JM
2867 if (Rc(ctx->opcode)) {
2868 if (unlikely(rA(ctx->opcode) == 0 ||
2869 rA(ctx->opcode) == rD(ctx->opcode))) {
e1833e1f 2870 GEN_EXCP_INVAL(ctx);
d9bce9d9
JM
2871 return;
2872 }
2873 }
a7812ae4 2874 EA = tcg_temp_new();
a7859e89 2875 gen_set_access_type(ACCESS_INT);
b61f2753 2876 gen_addr_imm_index(EA, ctx, 0x03);
d9bce9d9
JM
2877 if (ctx->opcode & 0x02) {
2878 /* lwa (lwau is undefined) */
b61f2753 2879 gen_qemu_ld32s(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
d9bce9d9
JM
2880 } else {
2881 /* ld - ldu */
b61f2753 2882 gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], EA, ctx->mem_idx);
d9bce9d9 2883 }
d9bce9d9 2884 if (Rc(ctx->opcode))
b61f2753
AJ
2885 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
2886 tcg_temp_free(EA);
d9bce9d9 2887}
be147d08
JM
2888/* lq */
2889GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2890{
2891#if defined(CONFIG_USER_ONLY)
2892 GEN_EXCP_PRIVOPC(ctx);
2893#else
2894 int ra, rd;
b61f2753 2895 TCGv EA;
be147d08
JM
2896
2897 /* Restore CPU state */
2898 if (unlikely(ctx->supervisor == 0)) {
2899 GEN_EXCP_PRIVOPC(ctx);
2900 return;
2901 }
2902 ra = rA(ctx->opcode);
2903 rd = rD(ctx->opcode);
2904 if (unlikely((rd & 1) || rd == ra)) {
2905 GEN_EXCP_INVAL(ctx);
2906 return;
2907 }
2908 if (unlikely(ctx->mem_idx & 1)) {
2909 /* Little-endian mode is not handled */
2910 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2911 return;
2912 }
a7812ae4 2913 EA = tcg_temp_new();
a7859e89 2914 gen_set_access_type(ACCESS_INT);
b61f2753
AJ
2915 gen_addr_imm_index(EA, ctx, 0x0F);
2916 gen_qemu_ld64(cpu_gpr[rd], EA, ctx->mem_idx);
2917 tcg_gen_addi_tl(EA, EA, 8);
2918 gen_qemu_ld64(cpu_gpr[rd+1], EA, ctx->mem_idx);
2919 tcg_temp_free(EA);
be147d08
JM
2920#endif
2921}
d9bce9d9 2922#endif
79aceca5
FB
2923
2924/*** Integer store ***/
0c8aacd4
AJ
2925#define GEN_ST(name, stop, opc, type) \
2926GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 2927{ \
0c8aacd4 2928 TCGv EA = tcg_temp_new(); \
a7859e89 2929 gen_set_access_type(ACCESS_INT); \
b61f2753 2930 gen_addr_imm_index(EA, ctx, 0); \
0c8aacd4 2931 gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753 2932 tcg_temp_free(EA); \
79aceca5
FB
2933}
2934
0c8aacd4
AJ
2935#define GEN_STU(name, stop, opc, type) \
2936GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 2937{ \
b61f2753 2938 TCGv EA; \
76a66253 2939 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 2940 GEN_EXCP_INVAL(ctx); \
9fddaa0c 2941 return; \
9a64fbe4 2942 } \
0c8aacd4 2943 EA = tcg_temp_new(); \
a7859e89 2944 gen_set_access_type(ACCESS_INT); \
9d53c753 2945 if (type == PPC_64B) \
b61f2753 2946 gen_addr_imm_index(EA, ctx, 0x03); \
9d53c753 2947 else \
b61f2753 2948 gen_addr_imm_index(EA, ctx, 0); \
0c8aacd4 2949 gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753
AJ
2950 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2951 tcg_temp_free(EA); \
79aceca5
FB
2952}
2953
0c8aacd4
AJ
2954#define GEN_STUX(name, stop, opc2, opc3, type) \
2955GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 2956{ \
b61f2753 2957 TCGv EA; \
76a66253 2958 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 2959 GEN_EXCP_INVAL(ctx); \
9fddaa0c 2960 return; \
9a64fbe4 2961 } \
0c8aacd4 2962 EA = tcg_temp_new(); \
a7859e89 2963 gen_set_access_type(ACCESS_INT); \
b61f2753 2964 gen_addr_reg_index(EA, ctx); \
0c8aacd4 2965 gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753
AJ
2966 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
2967 tcg_temp_free(EA); \
79aceca5
FB
2968}
2969
0c8aacd4
AJ
2970#define GEN_STX(name, stop, opc2, opc3, type) \
2971GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 2972{ \
0c8aacd4 2973 TCGv EA = tcg_temp_new(); \
a7859e89 2974 gen_set_access_type(ACCESS_INT); \
b61f2753 2975 gen_addr_reg_index(EA, ctx); \
0c8aacd4 2976 gen_qemu_##stop(cpu_gpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
b61f2753 2977 tcg_temp_free(EA); \
79aceca5
FB
2978}
2979
0c8aacd4
AJ
2980#define GEN_STS(name, stop, op, type) \
2981GEN_ST(name, stop, op | 0x20, type); \
2982GEN_STU(name, stop, op | 0x21, type); \
2983GEN_STUX(name, stop, 0x17, op | 0x01, type); \
2984GEN_STX(name, stop, 0x17, op | 0x00, type)
79aceca5
FB
2985
2986/* stb stbu stbux stbx */
0c8aacd4 2987GEN_STS(stb, st8, 0x06, PPC_INTEGER);
79aceca5 2988/* sth sthu sthux sthx */
0c8aacd4 2989GEN_STS(sth, st16, 0x0C, PPC_INTEGER);
79aceca5 2990/* stw stwu stwux stwx */
0c8aacd4 2991GEN_STS(stw, st32, 0x04, PPC_INTEGER);
d9bce9d9 2992#if defined(TARGET_PPC64)
0c8aacd4
AJ
2993GEN_STUX(std, st64, 0x15, 0x05, PPC_64B);
2994GEN_STX(std, st64, 0x15, 0x04, PPC_64B);
be147d08 2995GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
d9bce9d9 2996{
be147d08 2997 int rs;
b61f2753 2998 TCGv EA;
be147d08
JM
2999
3000 rs = rS(ctx->opcode);
3001 if ((ctx->opcode & 0x3) == 0x2) {
3002#if defined(CONFIG_USER_ONLY)
3003 GEN_EXCP_PRIVOPC(ctx);
3004#else
3005 /* stq */
3006 if (unlikely(ctx->supervisor == 0)) {
3007 GEN_EXCP_PRIVOPC(ctx);
3008 return;
3009 }
3010 if (unlikely(rs & 1)) {
e1833e1f 3011 GEN_EXCP_INVAL(ctx);
d9bce9d9
JM
3012 return;
3013 }
be147d08
JM
3014 if (unlikely(ctx->mem_idx & 1)) {
3015 /* Little-endian mode is not handled */
3016 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
3017 return;
3018 }
a7812ae4 3019 EA = tcg_temp_new();
a7859e89 3020 gen_set_access_type(ACCESS_INT);
b61f2753
AJ
3021 gen_addr_imm_index(EA, ctx, 0x03);
3022 gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
3023 tcg_gen_addi_tl(EA, EA, 8);
3024 gen_qemu_st64(cpu_gpr[rs+1], EA, ctx->mem_idx);
3025 tcg_temp_free(EA);
be147d08
JM
3026#endif
3027 } else {
3028 /* std / stdu */
3029 if (Rc(ctx->opcode)) {
3030 if (unlikely(rA(ctx->opcode) == 0)) {
3031 GEN_EXCP_INVAL(ctx);
3032 return;
3033 }
3034 }
a7812ae4 3035 EA = tcg_temp_new();
a7859e89 3036 gen_set_access_type(ACCESS_INT);
b61f2753
AJ
3037 gen_addr_imm_index(EA, ctx, 0x03);
3038 gen_qemu_st64(cpu_gpr[rs], EA, ctx->mem_idx);
be147d08 3039 if (Rc(ctx->opcode))
b61f2753
AJ
3040 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA);
3041 tcg_temp_free(EA);
d9bce9d9 3042 }
d9bce9d9
JM
3043}
3044#endif
79aceca5
FB
3045/*** Integer load and store with byte reverse ***/
3046/* lhbrx */
b61f2753
AJ
3047void always_inline gen_qemu_ld16ur(TCGv t0, TCGv t1, int flags)
3048{
a7812ae4
PB
3049 TCGv_i32 temp = tcg_temp_new_i32();
3050 gen_qemu_ld16u(t0, t1, flags);
3051 tcg_gen_trunc_tl_i32(temp, t0);
b61f2753
AJ
3052 tcg_gen_bswap16_i32(temp, temp);
3053 tcg_gen_extu_i32_tl(t0, temp);
a7812ae4 3054 tcg_temp_free_i32(temp);
b61f2753 3055}
0c8aacd4 3056GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
b61f2753 3057
79aceca5 3058/* lwbrx */
b61f2753
AJ
3059void always_inline gen_qemu_ld32ur(TCGv t0, TCGv t1, int flags)
3060{
a7812ae4
PB
3061 TCGv_i32 temp = tcg_temp_new_i32();
3062 gen_qemu_ld32u(t0, t1, flags);
3063 tcg_gen_trunc_tl_i32(temp, t0);
b61f2753
AJ
3064 tcg_gen_bswap_i32(temp, temp);
3065 tcg_gen_extu_i32_tl(t0, temp);
a7812ae4 3066 tcg_temp_free_i32(temp);
b61f2753 3067}
0c8aacd4 3068GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
b61f2753 3069
79aceca5 3070/* sthbrx */
b61f2753
AJ
3071void always_inline gen_qemu_st16r(TCGv t0, TCGv t1, int flags)
3072{
a7812ae4
PB
3073 TCGv_i32 temp = tcg_temp_new_i32();
3074 TCGv t2 = tcg_temp_new();
b61f2753
AJ
3075 tcg_gen_trunc_tl_i32(temp, t0);
3076 tcg_gen_ext16u_i32(temp, temp);
3077 tcg_gen_bswap16_i32(temp, temp);
a7812ae4
PB
3078 tcg_gen_extu_i32_tl(t2, temp);
3079 tcg_temp_free_i32(temp);
3080 gen_qemu_st16(t2, t1, flags);
3081 tcg_temp_free(t2);
b61f2753 3082}
0c8aacd4 3083GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER);
b61f2753 3084
79aceca5 3085/* stwbrx */
b61f2753
AJ
3086void always_inline gen_qemu_st32r(TCGv t0, TCGv t1, int flags)
3087{
a7812ae4
PB
3088 TCGv_i32 temp = tcg_temp_new_i32();
3089 TCGv t2 = tcg_temp_new();
b61f2753
AJ
3090 tcg_gen_trunc_tl_i32(temp, t0);
3091 tcg_gen_bswap_i32(temp, temp);
a7812ae4
PB
3092 tcg_gen_extu_i32_tl(t2, temp);
3093 tcg_temp_free_i32(temp);
87006d13 3094 gen_qemu_st32(t2, t1, flags);
a7812ae4 3095 tcg_temp_free(t2);
b61f2753 3096}
0c8aacd4 3097GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
79aceca5
FB
3098
3099/*** Integer load and store multiple ***/
3100/* lmw */
3101GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3102{
ff4a62cd
AJ
3103 TCGv t0 = tcg_temp_new();
3104 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
76a66253 3105 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3106 gen_update_nip(ctx, ctx->nip - 4);
ff4a62cd
AJ
3107 gen_addr_imm_index(t0, ctx, 0);
3108 gen_helper_lmw(t0, t1);
3109 tcg_temp_free(t0);
3110 tcg_temp_free_i32(t1);
79aceca5
FB
3111}
3112
3113/* stmw */
3114GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3115{
ff4a62cd
AJ
3116 TCGv t0 = tcg_temp_new();
3117 TCGv_i32 t1 = tcg_const_i32(rS(ctx->opcode));
76a66253 3118 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3119 gen_update_nip(ctx, ctx->nip - 4);
ff4a62cd
AJ
3120 gen_addr_imm_index(t0, ctx, 0);
3121 gen_helper_stmw(t0, t1);
3122 tcg_temp_free(t0);
3123 tcg_temp_free_i32(t1);
79aceca5
FB
3124}
3125
3126/*** Integer load and store strings ***/
3127/* lswi */
3fc6c082 3128/* PowerPC32 specification says we must generate an exception if
9a64fbe4
FB
3129 * rA is in the range of registers to be loaded.
3130 * In an other hand, IBM says this is valid, but rA won't be loaded.
3131 * For now, I'll follow the spec...
3132 */
05332d70 3133GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
79aceca5 3134{
dfbc799d
AJ
3135 TCGv t0;
3136 TCGv_i32 t1, t2;
79aceca5
FB
3137 int nb = NB(ctx->opcode);
3138 int start = rD(ctx->opcode);
9a64fbe4 3139 int ra = rA(ctx->opcode);
79aceca5
FB
3140 int nr;
3141
3142 if (nb == 0)
3143 nb = 32;
3144 nr = nb / 4;
76a66253
JM
3145 if (unlikely(((start + nr) > 32 &&
3146 start <= ra && (start + nr - 32) > ra) ||
3147 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
e1833e1f
JM
3148 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3149 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
9fddaa0c 3150 return;
297d8e62 3151 }
8dd4983c 3152 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3153 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d
AJ
3154 t0 = tcg_temp_new();
3155 gen_addr_register(t0, ctx);
3156 t1 = tcg_const_i32(nb);
3157 t2 = tcg_const_i32(start);
3158 gen_helper_lsw(t0, t1, t2);
3159 tcg_temp_free(t0);
3160 tcg_temp_free_i32(t1);
3161 tcg_temp_free_i32(t2);
79aceca5
FB
3162}
3163
3164/* lswx */
05332d70 3165GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
79aceca5 3166{
dfbc799d
AJ
3167 TCGv t0 = tcg_temp_new();
3168 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
3169 TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
3170 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
76a66253 3171 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3172 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d
AJ
3173 gen_addr_reg_index(t0, ctx);
3174 gen_helper_lswx(t0, t1, t2, t3);
3175 tcg_temp_free(t0);
3176 tcg_temp_free_i32(t1);
3177 tcg_temp_free_i32(t2);
3178 tcg_temp_free_i32(t3);
79aceca5
FB
3179}
3180
3181/* stswi */
05332d70 3182GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
79aceca5 3183{
4b3686fa 3184 int nb = NB(ctx->opcode);
dfbc799d
AJ
3185 TCGv t0 = tcg_temp_new();
3186 TCGv_i32 t1;
3187 TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode));
76a66253 3188 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3189 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d 3190 gen_addr_register(t0, ctx);
4b3686fa
FB
3191 if (nb == 0)
3192 nb = 32;
dfbc799d
AJ
3193 t1 = tcg_const_i32(nb);
3194 gen_helper_stsw(t0, t1, t2);
3195 tcg_temp_free(t0);
3196 tcg_temp_free_i32(t1);
3197 tcg_temp_free_i32(t2);
79aceca5
FB
3198}
3199
3200/* stswx */
05332d70 3201GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
79aceca5 3202{
dfbc799d
AJ
3203 TCGv t0 = tcg_temp_new();
3204 TCGv_i32 t1 = tcg_temp_new_i32();
3205 TCGv_i32 t2 = tcg_const_i32(rS(ctx->opcode));
8dd4983c 3206 /* NIP cannot be restored if the memory exception comes from an helper */
5fafdf24 3207 gen_update_nip(ctx, ctx->nip - 4);
dfbc799d
AJ
3208 gen_addr_reg_index(t0, ctx);
3209 tcg_gen_trunc_tl_i32(t1, cpu_xer);
3210 tcg_gen_andi_i32(t1, t1, 0x7F);
3211 gen_helper_stsw(t0, t1, t2);
3212 tcg_temp_free(t0);
3213 tcg_temp_free_i32(t1);
3214 tcg_temp_free_i32(t2);
79aceca5
FB
3215}
3216
3217/*** Memory synchronisation ***/
3218/* eieio */
0db1b20e 3219GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
79aceca5 3220{
79aceca5
FB
3221}
3222
3223/* isync */
0db1b20e 3224GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
79aceca5 3225{
e1833e1f 3226 GEN_STOP(ctx);
79aceca5
FB
3227}
3228
111bfab3 3229/* lwarx */
76a66253 3230GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
79aceca5 3231{
cf360a32 3232 TCGv t0 = tcg_temp_local_new();
a7859e89 3233 gen_set_access_type(ACCESS_RES);
cf360a32
AJ
3234 gen_addr_reg_index(t0, ctx);
3235 gen_check_align(ctx, t0, 0x03);
3236#if defined(TARGET_PPC64)
3237 if (!ctx->sf_mode)
3238 tcg_gen_ext32u_tl(t0, t0);
3239#endif
3240 gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx);
3241 tcg_gen_mov_tl(cpu_reserve, t0);
3242 tcg_temp_free(t0);
79aceca5
FB
3243}
3244
3245/* stwcx. */
c7697e1f 3246GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
79aceca5 3247{
cf360a32
AJ
3248 int l1 = gen_new_label();
3249 TCGv t0 = tcg_temp_local_new();
a7859e89 3250 gen_set_access_type(ACCESS_RES);
cf360a32
AJ
3251 gen_addr_reg_index(t0, ctx);
3252 gen_check_align(ctx, t0, 0x03);
3253#if defined(TARGET_PPC64)
3254 if (!ctx->sf_mode)
3255 tcg_gen_ext32u_tl(t0, t0);
3256#endif
3257 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3258 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3259 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3260 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3261 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3262 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx);
3263 gen_set_label(l1);
3264 tcg_gen_movi_tl(cpu_reserve, -1);
3265 tcg_temp_free(t0);
79aceca5
FB
3266}
3267
426613db 3268#if defined(TARGET_PPC64)
426613db 3269/* ldarx */
a750fc0b 3270GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
426613db 3271{
cf360a32 3272 TCGv t0 = tcg_temp_local_new();
a7859e89 3273 gen_set_access_type(ACCESS_RES);
cf360a32
AJ
3274 gen_addr_reg_index(t0, ctx);
3275 gen_check_align(ctx, t0, 0x07);
3276 if (!ctx->sf_mode)
3277 tcg_gen_ext32u_tl(t0, t0);
3278 gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx);
3279 tcg_gen_mov_tl(cpu_reserve, t0);
3280 tcg_temp_free(t0);
426613db
JM
3281}
3282
3283/* stdcx. */
c7697e1f 3284GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
426613db 3285{
cf360a32
AJ
3286 int l1 = gen_new_label();
3287 TCGv t0 = tcg_temp_local_new();
a7859e89 3288 gen_set_access_type(ACCESS_RES);
cf360a32
AJ
3289 gen_addr_reg_index(t0, ctx);
3290 gen_check_align(ctx, t0, 0x07);
3291 if (!ctx->sf_mode)
3292 tcg_gen_ext32u_tl(t0, t0);
3293 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_xer);
3294 tcg_gen_shri_i32(cpu_crf[0], cpu_crf[0], XER_SO);
3295 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 1);
3296 tcg_gen_brcond_tl(TCG_COND_NE, t0, cpu_reserve, l1);
3297 tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], 1 << CRF_EQ);
3298 gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], t0, ctx->mem_idx);
3299 gen_set_label(l1);
3300 tcg_gen_movi_tl(cpu_reserve, -1);
3301 tcg_temp_free(t0);
426613db
JM
3302}
3303#endif /* defined(TARGET_PPC64) */
3304
79aceca5 3305/* sync */
a902d886 3306GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
79aceca5 3307{
79aceca5
FB
3308}
3309
0db1b20e
JM
3310/* wait */
3311GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
3312{
931ff272
AJ
3313 TCGv_i32 t0 = tcg_temp_new_i32();
3314 tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3315 tcg_temp_free_i32(t0);
0db1b20e 3316 /* Stop translation, as the CPU is supposed to sleep from now */
be147d08 3317 GEN_EXCP(ctx, EXCP_HLT, 1);
0db1b20e
JM
3318}
3319
79aceca5 3320/*** Floating-point load ***/
a0d7d5a7
AJ
3321#define GEN_LDF(name, ldop, opc, type) \
3322GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3323{ \
a0d7d5a7 3324 TCGv EA; \
76a66253 3325 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3326 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3327 return; \
3328 } \
a7859e89 3329 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3330 EA = tcg_temp_new(); \
3331 gen_addr_imm_index(EA, ctx, 0); \
3332 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3333 tcg_temp_free(EA); \
79aceca5
FB
3334}
3335
a0d7d5a7
AJ
3336#define GEN_LDUF(name, ldop, opc, type) \
3337GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3338{ \
a0d7d5a7 3339 TCGv EA; \
76a66253 3340 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3341 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3342 return; \
3343 } \
76a66253 3344 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3345 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3346 return; \
9a64fbe4 3347 } \
a7859e89 3348 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3349 EA = tcg_temp_new(); \
3350 gen_addr_imm_index(EA, ctx, 0); \
3351 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3352 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3353 tcg_temp_free(EA); \
79aceca5
FB
3354}
3355
a0d7d5a7
AJ
3356#define GEN_LDUXF(name, ldop, opc, type) \
3357GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
79aceca5 3358{ \
a0d7d5a7 3359 TCGv EA; \
76a66253 3360 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3361 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3362 return; \
3363 } \
76a66253 3364 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3365 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3366 return; \
9a64fbe4 3367 } \
a7859e89 3368 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3369 EA = tcg_temp_new(); \
3370 gen_addr_reg_index(EA, ctx); \
3371 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3372 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3373 tcg_temp_free(EA); \
79aceca5
FB
3374}
3375
a0d7d5a7
AJ
3376#define GEN_LDXF(name, ldop, opc2, opc3, type) \
3377GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 3378{ \
a0d7d5a7 3379 TCGv EA; \
76a66253 3380 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3381 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3382 return; \
3383 } \
a7859e89 3384 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3385 EA = tcg_temp_new(); \
3386 gen_addr_reg_index(EA, ctx); \
3387 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3388 tcg_temp_free(EA); \
79aceca5
FB
3389}
3390
a0d7d5a7
AJ
3391#define GEN_LDFS(name, ldop, op, type) \
3392GEN_LDF(name, ldop, op | 0x20, type); \
3393GEN_LDUF(name, ldop, op | 0x21, type); \
3394GEN_LDUXF(name, ldop, op | 0x01, type); \
3395GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3396
3397static always_inline void gen_qemu_ld32fs(TCGv_i64 arg1, TCGv arg2, int flags)
3398{
3399 TCGv t0 = tcg_temp_new();
3400 TCGv_i32 t1 = tcg_temp_new_i32();
3401 gen_qemu_ld32u(t0, arg2, flags);
3402 tcg_gen_trunc_tl_i32(t1, t0);
3403 tcg_temp_free(t0);
3404 gen_helper_float32_to_float64(arg1, t1);
3405 tcg_temp_free_i32(t1);
3406}
79aceca5 3407
a0d7d5a7
AJ
3408 /* lfd lfdu lfdux lfdx */
3409GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3410 /* lfs lfsu lfsux lfsx */
3411GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
79aceca5
FB
3412
3413/*** Floating-point store ***/
a0d7d5a7
AJ
3414#define GEN_STF(name, stop, opc, type) \
3415GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3416{ \
a0d7d5a7 3417 TCGv EA; \
76a66253 3418 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3419 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3420 return; \
3421 } \
a7859e89 3422 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3423 EA = tcg_temp_new(); \
3424 gen_addr_imm_index(EA, ctx, 0); \
3425 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3426 tcg_temp_free(EA); \
79aceca5
FB
3427}
3428
a0d7d5a7
AJ
3429#define GEN_STUF(name, stop, opc, type) \
3430GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3431{ \
a0d7d5a7 3432 TCGv EA; \
76a66253 3433 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3434 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3435 return; \
3436 } \
76a66253 3437 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3438 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3439 return; \
9a64fbe4 3440 } \
a7859e89 3441 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3442 EA = tcg_temp_new(); \
3443 gen_addr_imm_index(EA, ctx, 0); \
3444 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3445 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3446 tcg_temp_free(EA); \
79aceca5
FB
3447}
3448
a0d7d5a7
AJ
3449#define GEN_STUXF(name, stop, opc, type) \
3450GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
79aceca5 3451{ \
a0d7d5a7 3452 TCGv EA; \
76a66253 3453 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3454 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3455 return; \
3456 } \
76a66253 3457 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3458 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3459 return; \
9a64fbe4 3460 } \
a7859e89 3461 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3462 EA = tcg_temp_new(); \
3463 gen_addr_reg_index(EA, ctx); \
3464 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3465 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3466 tcg_temp_free(EA); \
79aceca5
FB
3467}
3468
a0d7d5a7
AJ
3469#define GEN_STXF(name, stop, opc2, opc3, type) \
3470GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 3471{ \
a0d7d5a7 3472 TCGv EA; \
76a66253 3473 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3474 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3475 return; \
3476 } \
a7859e89 3477 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3478 EA = tcg_temp_new(); \
3479 gen_addr_reg_index(EA, ctx); \
3480 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3481 tcg_temp_free(EA); \
79aceca5
FB
3482}
3483
a0d7d5a7
AJ
3484#define GEN_STFS(name, stop, op, type) \
3485GEN_STF(name, stop, op | 0x20, type); \
3486GEN_STUF(name, stop, op | 0x21, type); \
3487GEN_STUXF(name, stop, op | 0x01, type); \
3488GEN_STXF(name, stop, 0x17, op | 0x00, type)
3489
3490static always_inline void gen_qemu_st32fs(TCGv_i64 arg1, TCGv arg2, int flags)
3491{
3492 TCGv_i32 t0 = tcg_temp_new_i32();
3493 TCGv t1 = tcg_temp_new();
3494 gen_helper_float64_to_float32(t0, arg1);
3495 tcg_gen_extu_i32_tl(t1, t0);
3496 tcg_temp_free_i32(t0);
3497 gen_qemu_st32(t1, arg2, flags);
3498 tcg_temp_free(t1);
3499}
79aceca5
FB
3500
3501/* stfd stfdu stfdux stfdx */
a0d7d5a7 3502GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
79aceca5 3503/* stfs stfsu stfsux stfsx */
a0d7d5a7 3504GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
79aceca5
FB
3505
3506/* Optional: */
a0d7d5a7
AJ
3507static always_inline void gen_qemu_st32fiw(TCGv_i64 arg1, TCGv arg2, int flags)
3508{
3509 TCGv t0 = tcg_temp_new();
3510 tcg_gen_trunc_i64_tl(t0, arg1),
3511 gen_qemu_st32(t0, arg2, flags);
3512 tcg_temp_free(t0);
3513}
79aceca5 3514/* stfiwx */
a0d7d5a7 3515GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
79aceca5
FB
3516
3517/*** Branch ***/
b068d6a7
JM
3518static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3519 target_ulong dest)
c1942362
FB
3520{
3521 TranslationBlock *tb;
3522 tb = ctx->tb;
a2ffb812
AJ
3523#if defined(TARGET_PPC64)
3524 if (!ctx->sf_mode)
3525 dest = (uint32_t) dest;
3526#endif
57fec1fe 3527 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
8cbcb4fa 3528 likely(!ctx->singlestep_enabled)) {
57fec1fe 3529 tcg_gen_goto_tb(n);
a2ffb812 3530 tcg_gen_movi_tl(cpu_nip, dest & ~3);
57fec1fe 3531 tcg_gen_exit_tb((long)tb + n);
c1942362 3532 } else {
a2ffb812 3533 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cbcb4fa
AJ
3534 if (unlikely(ctx->singlestep_enabled)) {
3535 if ((ctx->singlestep_enabled &
bdc4e053 3536 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
8cbcb4fa
AJ
3537 ctx->exception == POWERPC_EXCP_BRANCH) {
3538 target_ulong tmp = ctx->nip;
3539 ctx->nip = dest;
3540 GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
3541 ctx->nip = tmp;
3542 }
3543 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3544 gen_update_nip(ctx, dest);
64adab3f 3545 gen_helper_raise_debug();
8cbcb4fa
AJ
3546 }
3547 }
57fec1fe 3548 tcg_gen_exit_tb(0);
c1942362 3549 }
c53be334
FB
3550}
3551
b068d6a7 3552static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
e1833e1f
JM
3553{
3554#if defined(TARGET_PPC64)
a2ffb812
AJ
3555 if (ctx->sf_mode == 0)
3556 tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
e1833e1f
JM
3557 else
3558#endif
a2ffb812 3559 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
3560}
3561
79aceca5
FB
3562/* b ba bl bla */
3563GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3564{
76a66253 3565 target_ulong li, target;
38a64f9d 3566
8cbcb4fa 3567 ctx->exception = POWERPC_EXCP_BRANCH;
38a64f9d 3568 /* sign extend LI */
76a66253 3569#if defined(TARGET_PPC64)
d9bce9d9
JM
3570 if (ctx->sf_mode)
3571 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3572 else
76a66253 3573#endif
d9bce9d9 3574 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
76a66253 3575 if (likely(AA(ctx->opcode) == 0))
046d6672 3576 target = ctx->nip + li - 4;
79aceca5 3577 else
9a64fbe4 3578 target = li;
e1833e1f
JM
3579 if (LK(ctx->opcode))
3580 gen_setlr(ctx, ctx->nip);
c1942362 3581 gen_goto_tb(ctx, 0, target);
79aceca5
FB
3582}
3583
e98a6e40
FB
3584#define BCOND_IM 0
3585#define BCOND_LR 1
3586#define BCOND_CTR 2
3587
b068d6a7 3588static always_inline void gen_bcond (DisasContext *ctx, int type)
d9bce9d9 3589{
d9bce9d9 3590 uint32_t bo = BO(ctx->opcode);
a2ffb812
AJ
3591 int l1 = gen_new_label();
3592 TCGv target;
e98a6e40 3593
8cbcb4fa 3594 ctx->exception = POWERPC_EXCP_BRANCH;
a2ffb812 3595 if (type == BCOND_LR || type == BCOND_CTR) {
a7812ae4 3596 target = tcg_temp_local_new();
a2ffb812
AJ
3597 if (type == BCOND_CTR)
3598 tcg_gen_mov_tl(target, cpu_ctr);
3599 else
3600 tcg_gen_mov_tl(target, cpu_lr);
e98a6e40 3601 }
e1833e1f
JM
3602 if (LK(ctx->opcode))
3603 gen_setlr(ctx, ctx->nip);
a2ffb812
AJ
3604 l1 = gen_new_label();
3605 if ((bo & 0x4) == 0) {
3606 /* Decrement and test CTR */
a7812ae4 3607 TCGv temp = tcg_temp_new();
a2ffb812
AJ
3608 if (unlikely(type == BCOND_CTR)) {
3609 GEN_EXCP_INVAL(ctx);
3610 return;
3611 }
3612 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
d9bce9d9 3613#if defined(TARGET_PPC64)
a2ffb812
AJ
3614 if (!ctx->sf_mode)
3615 tcg_gen_ext32u_tl(temp, cpu_ctr);
3616 else
d9bce9d9 3617#endif
a2ffb812
AJ
3618 tcg_gen_mov_tl(temp, cpu_ctr);
3619 if (bo & 0x2) {
3620 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3621 } else {
3622 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
e98a6e40 3623 }
a7812ae4 3624 tcg_temp_free(temp);
a2ffb812
AJ
3625 }
3626 if ((bo & 0x10) == 0) {
3627 /* Test CR */
3628 uint32_t bi = BI(ctx->opcode);
3629 uint32_t mask = 1 << (3 - (bi & 0x03));
a7812ae4 3630 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 3631
d9bce9d9 3632 if (bo & 0x8) {
a2ffb812
AJ
3633 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3634 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 3635 } else {
a2ffb812
AJ
3636 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3637 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 3638 }
a7812ae4 3639 tcg_temp_free_i32(temp);
d9bce9d9 3640 }
e98a6e40 3641 if (type == BCOND_IM) {
a2ffb812
AJ
3642 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3643 if (likely(AA(ctx->opcode) == 0)) {
3644 gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3645 } else {
3646 gen_goto_tb(ctx, 0, li);
3647 }
c53be334 3648 gen_set_label(l1);
c1942362 3649 gen_goto_tb(ctx, 1, ctx->nip);
e98a6e40 3650 } else {
d9bce9d9 3651#if defined(TARGET_PPC64)
a2ffb812
AJ
3652 if (!(ctx->sf_mode))
3653 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3654 else
3655#endif
3656 tcg_gen_andi_tl(cpu_nip, target, ~3);
3657 tcg_gen_exit_tb(0);
3658 gen_set_label(l1);
3659#if defined(TARGET_PPC64)
3660 if (!(ctx->sf_mode))
3661 tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
d9bce9d9
JM
3662 else
3663#endif
a2ffb812 3664 tcg_gen_movi_tl(cpu_nip, ctx->nip);
57fec1fe 3665 tcg_gen_exit_tb(0);
08e46e54 3666 }
e98a6e40
FB
3667}
3668
3669GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3b46e624 3670{
e98a6e40
FB
3671 gen_bcond(ctx, BCOND_IM);
3672}
3673
3674GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3b46e624 3675{
e98a6e40
FB
3676 gen_bcond(ctx, BCOND_CTR);
3677}
3678
3679GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3b46e624 3680{
e98a6e40
FB
3681 gen_bcond(ctx, BCOND_LR);
3682}
79aceca5
FB
3683
3684/*** Condition register logical ***/
e1571908
AJ
3685#define GEN_CRLOGIC(name, tcg_op, opc) \
3686GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
79aceca5 3687{ \
fc0d441e
JM
3688 uint8_t bitmask; \
3689 int sh; \
a7812ae4 3690 TCGv_i32 t0, t1; \
fc0d441e 3691 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 3692 t0 = tcg_temp_new_i32(); \
fc0d441e 3693 if (sh > 0) \
fea0c503 3694 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 3695 else if (sh < 0) \
fea0c503 3696 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 3697 else \
fea0c503 3698 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 3699 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
3700 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3701 if (sh > 0) \
fea0c503 3702 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 3703 else if (sh < 0) \
fea0c503 3704 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 3705 else \
fea0c503
AJ
3706 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3707 tcg_op(t0, t0, t1); \
fc0d441e 3708 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
fea0c503
AJ
3709 tcg_gen_andi_i32(t0, t0, bitmask); \
3710 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3711 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
3712 tcg_temp_free_i32(t0); \
3713 tcg_temp_free_i32(t1); \
79aceca5
FB
3714}
3715
3716/* crand */
e1571908 3717GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 3718/* crandc */
e1571908 3719GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 3720/* creqv */
e1571908 3721GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 3722/* crnand */
e1571908 3723GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 3724/* crnor */
e1571908 3725GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 3726/* cror */
e1571908 3727GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 3728/* crorc */
e1571908 3729GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 3730/* crxor */
e1571908 3731GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
79aceca5
FB
3732/* mcrf */
3733GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3734{
47e4661c 3735 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
3736}
3737
3738/*** System linkage ***/
3739/* rfi (supervisor only) */
76a66253 3740GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
79aceca5 3741{
9a64fbe4 3742#if defined(CONFIG_USER_ONLY)
e1833e1f 3743 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4
FB
3744#else
3745 /* Restore CPU state */
76a66253 3746 if (unlikely(!ctx->supervisor)) {
e1833e1f 3747 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 3748 return;
9a64fbe4 3749 }
d72a19f7 3750 gen_helper_rfi();
e1833e1f 3751 GEN_SYNC(ctx);
9a64fbe4 3752#endif
79aceca5
FB
3753}
3754
426613db 3755#if defined(TARGET_PPC64)
a750fc0b 3756GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
426613db
JM
3757{
3758#if defined(CONFIG_USER_ONLY)
e1833e1f 3759 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
3760#else
3761 /* Restore CPU state */
3762 if (unlikely(!ctx->supervisor)) {
e1833e1f 3763 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
3764 return;
3765 }
d72a19f7 3766 gen_helper_rfid();
e1833e1f 3767 GEN_SYNC(ctx);
426613db
JM
3768#endif
3769}
426613db 3770
5b8105fa 3771GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
be147d08
JM
3772{
3773#if defined(CONFIG_USER_ONLY)
3774 GEN_EXCP_PRIVOPC(ctx);
3775#else
3776 /* Restore CPU state */
3777 if (unlikely(ctx->supervisor <= 1)) {
3778 GEN_EXCP_PRIVOPC(ctx);
3779 return;
3780 }
d72a19f7 3781 gen_helper_hrfid();
be147d08
JM
3782 GEN_SYNC(ctx);
3783#endif
3784}
3785#endif
3786
79aceca5 3787/* sc */
417bf010
JM
3788#if defined(CONFIG_USER_ONLY)
3789#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3790#else
3791#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3792#endif
e1833e1f 3793GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
79aceca5 3794{
e1833e1f
JM
3795 uint32_t lev;
3796
3797 lev = (ctx->opcode >> 5) & 0x7F;
417bf010 3798 GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
3799}
3800
3801/*** Trap ***/
3802/* tw */
76a66253 3803GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
79aceca5 3804{
cab3bee2 3805 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
a0ae05aa 3806 /* Update the nip since this might generate a trap exception */
d9bce9d9 3807 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3808 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3809 tcg_temp_free_i32(t0);
79aceca5
FB
3810}
3811
3812/* twi */
3813GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3814{
cab3bee2
AJ
3815 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3816 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3817 /* Update the nip since this might generate a trap exception */
3818 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3819 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3820 tcg_temp_free(t0);
3821 tcg_temp_free_i32(t1);
79aceca5
FB
3822}
3823
d9bce9d9
JM
3824#if defined(TARGET_PPC64)
3825/* td */
3826GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3827{
cab3bee2 3828 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3829 /* Update the nip since this might generate a trap exception */
3830 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3831 gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3832 tcg_temp_free_i32(t0);
d9bce9d9
JM
3833}
3834
3835/* tdi */
3836GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3837{
cab3bee2
AJ
3838 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3839 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3840 /* Update the nip since this might generate a trap exception */
3841 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3842 gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3843 tcg_temp_free(t0);
3844 tcg_temp_free_i32(t1);
d9bce9d9
JM
3845}
3846#endif
3847
79aceca5 3848/*** Processor control ***/
79aceca5
FB
3849/* mcrxr */
3850GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3851{
3d7b417e
AJ
3852 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3853 tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
269f3e95 3854 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
79aceca5
FB
3855}
3856
3857/* mfcr */
76a66253 3858GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
79aceca5 3859{
76a66253 3860 uint32_t crm, crn;
3b46e624 3861
76a66253
JM
3862 if (likely(ctx->opcode & 0x00100000)) {
3863 crm = CRM(ctx->opcode);
3864 if (likely((crm ^ (crm - 1)) == 0)) {
3865 crn = ffs(crm);
e1571908 3866 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
76a66253 3867 }
d9bce9d9 3868 } else {
a7812ae4 3869 gen_helper_load_cr(cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 3870 }
79aceca5
FB
3871}
3872
3873/* mfmsr */
3874GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3875{
9a64fbe4 3876#if defined(CONFIG_USER_ONLY)
e1833e1f 3877 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3878#else
76a66253 3879 if (unlikely(!ctx->supervisor)) {
e1833e1f 3880 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3881 return;
9a64fbe4 3882 }
6527f6ea 3883 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_msr);
9a64fbe4 3884#endif
79aceca5
FB
3885}
3886
a11b8151 3887#if 1
6f2d8978 3888#define SPR_NOACCESS ((void *)(-1UL))
3fc6c082
FB
3889#else
3890static void spr_noaccess (void *opaque, int sprn)
3891{
3892 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3893 printf("ERROR: try to access SPR %d !\n", sprn);
3894}
3895#define SPR_NOACCESS (&spr_noaccess)
3896#endif
3897
79aceca5 3898/* mfspr */
b068d6a7 3899static always_inline void gen_op_mfspr (DisasContext *ctx)
79aceca5 3900{
3fc6c082 3901 void (*read_cb)(void *opaque, int sprn);
79aceca5
FB
3902 uint32_t sprn = SPR(ctx->opcode);
3903
3fc6c082 3904#if !defined(CONFIG_USER_ONLY)
be147d08
JM
3905 if (ctx->supervisor == 2)
3906 read_cb = ctx->spr_cb[sprn].hea_read;
7863667f 3907 else if (ctx->supervisor)
3fc6c082
FB
3908 read_cb = ctx->spr_cb[sprn].oea_read;
3909 else
9a64fbe4 3910#endif
3fc6c082 3911 read_cb = ctx->spr_cb[sprn].uea_read;
76a66253
JM
3912 if (likely(read_cb != NULL)) {
3913 if (likely(read_cb != SPR_NOACCESS)) {
3fc6c082 3914 (*read_cb)(ctx, sprn);
f78fb44e 3915 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3fc6c082
FB
3916 } else {
3917 /* Privilege exception */
9fceefa7
JM
3918 /* This is a hack to avoid warnings when running Linux:
3919 * this OS breaks the PowerPC virtualisation model,
3920 * allowing userland application to read the PVR
3921 */
3922 if (sprn != SPR_PVR) {
3923 if (loglevel != 0) {
6b542af7 3924 fprintf(logfile, "Trying to read privileged spr %d %03x at "
077fc206 3925 ADDRX "\n", sprn, sprn, ctx->nip);
9fceefa7 3926 }
077fc206
JM
3927 printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3928 sprn, sprn, ctx->nip);
f24e5695 3929 }
e1833e1f 3930 GEN_EXCP_PRIVREG(ctx);
79aceca5 3931 }
3fc6c082
FB
3932 } else {
3933 /* Not defined */
4a057712 3934 if (loglevel != 0) {
077fc206
JM
3935 fprintf(logfile, "Trying to read invalid spr %d %03x at "
3936 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 3937 }
077fc206
JM
3938 printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3939 sprn, sprn, ctx->nip);
e1833e1f
JM
3940 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3941 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 3942 }
79aceca5
FB
3943}
3944
3fc6c082 3945GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
79aceca5 3946{
3fc6c082 3947 gen_op_mfspr(ctx);
76a66253 3948}
3fc6c082
FB
3949
3950/* mftb */
a750fc0b 3951GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3fc6c082
FB
3952{
3953 gen_op_mfspr(ctx);
79aceca5
FB
3954}
3955
3956/* mtcrf */
8dd4983c 3957GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
79aceca5 3958{
76a66253 3959 uint32_t crm, crn;
3b46e624 3960
76a66253
JM
3961 crm = CRM(ctx->opcode);
3962 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
a7812ae4 3963 TCGv_i32 temp = tcg_temp_new_i32();
76a66253 3964 crn = ffs(crm);
a7812ae4
PB
3965 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3966 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
e1571908 3967 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
a7812ae4 3968 tcg_temp_free_i32(temp);
76a66253 3969 } else {
a7812ae4
PB
3970 TCGv_i32 temp = tcg_const_i32(crm);
3971 gen_helper_store_cr(cpu_gpr[rS(ctx->opcode)], temp);
3972 tcg_temp_free_i32(temp);
76a66253 3973 }
79aceca5
FB
3974}
3975
3976/* mtmsr */
426613db 3977#if defined(TARGET_PPC64)
be147d08 3978GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
426613db
JM
3979{
3980#if defined(CONFIG_USER_ONLY)
e1833e1f 3981 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3982#else
3983 if (unlikely(!ctx->supervisor)) {
e1833e1f 3984 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3985 return;
3986 }
f78fb44e 3987 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
3988 if (ctx->opcode & 0x00010000) {
3989 /* Special form that does not need any synchronisation */
6527f6ea
AJ
3990 TCGv t0 = tcg_temp_new();
3991 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
3992 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
3993 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
3994 tcg_temp_free(t0);
be147d08 3995 } else {
056b05f8
JM
3996 /* XXX: we need to update nip before the store
3997 * if we enter power saving mode, we will exit the loop
3998 * directly from ppc_store_msr
3999 */
be147d08 4000 gen_update_nip(ctx, ctx->nip);
6527f6ea 4001 gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
4002 /* Must stop the translation as machine state (may have) changed */
4003 /* Note that mtmsr is not always defined as context-synchronizing */
056b05f8 4004 ctx->exception = POWERPC_EXCP_STOP;
be147d08 4005 }
426613db
JM
4006#endif
4007}
4008#endif
4009
79aceca5
FB
4010GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
4011{
9a64fbe4 4012#if defined(CONFIG_USER_ONLY)
e1833e1f 4013 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4014#else
76a66253 4015 if (unlikely(!ctx->supervisor)) {
e1833e1f 4016 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4017 return;
9a64fbe4 4018 }
f78fb44e 4019 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
4020 if (ctx->opcode & 0x00010000) {
4021 /* Special form that does not need any synchronisation */
6527f6ea
AJ
4022 TCGv t0 = tcg_temp_new();
4023 tcg_gen_andi_tl(t0, cpu_gpr[rS(ctx->opcode)], (1 << MSR_RI) | (1 << MSR_EE));
4024 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~((1 << MSR_RI) | (1 << MSR_EE)));
4025 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
4026 tcg_temp_free(t0);
be147d08 4027 } else {
056b05f8
JM
4028 /* XXX: we need to update nip before the store
4029 * if we enter power saving mode, we will exit the loop
4030 * directly from ppc_store_msr
4031 */
be147d08 4032 gen_update_nip(ctx, ctx->nip);
d9bce9d9 4033#if defined(TARGET_PPC64)
6527f6ea
AJ
4034 if (!ctx->sf_mode) {
4035 TCGv t0 = tcg_temp_new();
4036 TCGv t1 = tcg_temp_new();
4037 tcg_gen_andi_tl(t0, cpu_msr, 0xFFFFFFFF00000000ULL);
4038 tcg_gen_ext32u_tl(t1, cpu_gpr[rS(ctx->opcode)]);
4039 tcg_gen_or_tl(t0, t0, t1);
4040 tcg_temp_free(t1);
4041 gen_helper_store_msr(t0);
4042 tcg_temp_free(t0);
4043 } else
d9bce9d9 4044#endif
6527f6ea 4045 gen_helper_store_msr(cpu_gpr[rS(ctx->opcode)]);
be147d08 4046 /* Must stop the translation as machine state (may have) changed */
6527f6ea 4047 /* Note that mtmsr is not always defined as context-synchronizing */
056b05f8 4048 ctx->exception = POWERPC_EXCP_STOP;
be147d08 4049 }
9a64fbe4 4050#endif
79aceca5
FB
4051}
4052
4053/* mtspr */
4054GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
4055{
3fc6c082 4056 void (*write_cb)(void *opaque, int sprn);
79aceca5
FB
4057 uint32_t sprn = SPR(ctx->opcode);
4058
3fc6c082 4059#if !defined(CONFIG_USER_ONLY)
be147d08
JM
4060 if (ctx->supervisor == 2)
4061 write_cb = ctx->spr_cb[sprn].hea_write;
7863667f 4062 else if (ctx->supervisor)
3fc6c082
FB
4063 write_cb = ctx->spr_cb[sprn].oea_write;
4064 else
9a64fbe4 4065#endif
3fc6c082 4066 write_cb = ctx->spr_cb[sprn].uea_write;
76a66253
JM
4067 if (likely(write_cb != NULL)) {
4068 if (likely(write_cb != SPR_NOACCESS)) {
f78fb44e 4069 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3fc6c082
FB
4070 (*write_cb)(ctx, sprn);
4071 } else {
4072 /* Privilege exception */
4a057712 4073 if (loglevel != 0) {
077fc206
JM
4074 fprintf(logfile, "Trying to write privileged spr %d %03x at "
4075 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 4076 }
077fc206
JM
4077 printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
4078 sprn, sprn, ctx->nip);
e1833e1f 4079 GEN_EXCP_PRIVREG(ctx);
76a66253 4080 }
3fc6c082
FB
4081 } else {
4082 /* Not defined */
4a057712 4083 if (loglevel != 0) {
077fc206
JM
4084 fprintf(logfile, "Trying to write invalid spr %d %03x at "
4085 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 4086 }
077fc206
JM
4087 printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
4088 sprn, sprn, ctx->nip);
e1833e1f
JM
4089 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
4090 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 4091 }
79aceca5
FB
4092}
4093
4094/*** Cache management ***/
79aceca5 4095/* dcbf */
0db1b20e 4096GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
79aceca5 4097{
dac454af 4098 /* XXX: specification says this is treated as a load by the MMU */
a7812ae4 4099 TCGv t0 = tcg_temp_new();
a7859e89 4100 gen_set_access_type(ACCESS_CACHE);
fea0c503
AJ
4101 gen_addr_reg_index(t0, ctx);
4102 gen_qemu_ld8u(t0, t0, ctx->mem_idx);
4103 tcg_temp_free(t0);
79aceca5
FB
4104}
4105
4106/* dcbi (Supervisor only) */
9a64fbe4 4107GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
79aceca5 4108{
a541f297 4109#if defined(CONFIG_USER_ONLY)
e1833e1f 4110 GEN_EXCP_PRIVOPC(ctx);
a541f297 4111#else
b61f2753 4112 TCGv EA, val;
76a66253 4113 if (unlikely(!ctx->supervisor)) {
e1833e1f 4114 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4115 return;
9a64fbe4 4116 }
a7812ae4 4117 EA = tcg_temp_new();
a7859e89 4118 gen_set_access_type(ACCESS_CACHE);
b61f2753 4119 gen_addr_reg_index(EA, ctx);
a7812ae4 4120 val = tcg_temp_new();
76a66253 4121 /* XXX: specification says this should be treated as a store by the MMU */
b61f2753
AJ
4122 gen_qemu_ld8u(val, EA, ctx->mem_idx);
4123 gen_qemu_st8(val, EA, ctx->mem_idx);
4124 tcg_temp_free(val);
4125 tcg_temp_free(EA);
a541f297 4126#endif
79aceca5
FB
4127}
4128
4129/* dcdst */
9a64fbe4 4130GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
79aceca5 4131{
76a66253 4132 /* XXX: specification say this is treated as a load by the MMU */
a7812ae4 4133 TCGv t0 = tcg_temp_new();
a7859e89 4134 gen_set_access_type(ACCESS_CACHE);
fea0c503
AJ
4135 gen_addr_reg_index(t0, ctx);
4136 gen_qemu_ld8u(t0, t0, ctx->mem_idx);
4137 tcg_temp_free(t0);
79aceca5
FB
4138}
4139
4140/* dcbt */
0db1b20e 4141GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
79aceca5 4142{
0db1b20e 4143 /* interpreted as no-op */
76a66253
JM
4144 /* XXX: specification say this is treated as a load by the MMU
4145 * but does not generate any exception
4146 */
79aceca5
FB
4147}
4148
4149/* dcbtst */
0db1b20e 4150GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
79aceca5 4151{
0db1b20e 4152 /* interpreted as no-op */
76a66253
JM
4153 /* XXX: specification say this is treated as a load by the MMU
4154 * but does not generate any exception
4155 */
79aceca5
FB
4156}
4157
4158/* dcbz */
d63001d1 4159GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
79aceca5 4160{
799a8c8d
AJ
4161 TCGv t0 = tcg_temp_new();
4162 gen_addr_reg_index(t0, ctx);
4163 /* NIP cannot be restored if the memory exception comes from an helper */
4164 gen_update_nip(ctx, ctx->nip - 4);
4165 gen_helper_dcbz(t0);
4166 tcg_temp_free(t0);
d63001d1
JM
4167}
4168
c7697e1f 4169GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
d63001d1 4170{
799a8c8d
AJ
4171 TCGv t0 = tcg_temp_new();
4172 gen_addr_reg_index(t0, ctx);
4173 /* NIP cannot be restored if the memory exception comes from an helper */
4174 gen_update_nip(ctx, ctx->nip - 4);
d63001d1 4175 if (ctx->opcode & 0x00200000)
799a8c8d 4176 gen_helper_dcbz(t0);
d63001d1 4177 else
799a8c8d
AJ
4178 gen_helper_dcbz_970(t0);
4179 tcg_temp_free(t0);
79aceca5
FB
4180}
4181
4182/* icbi */
1b413d55 4183GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
79aceca5 4184{
37d269df 4185 TCGv t0 = tcg_temp_new();
30032c94
JM
4186 /* NIP cannot be restored if the memory exception comes from an helper */
4187 gen_update_nip(ctx, ctx->nip - 4);
37d269df
AJ
4188 gen_addr_reg_index(t0, ctx);
4189 gen_helper_icbi(t0);
4190 tcg_temp_free(t0);
79aceca5
FB
4191}
4192
4193/* Optional: */
4194/* dcba */
a750fc0b 4195GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
79aceca5 4196{
0db1b20e
JM
4197 /* interpreted as no-op */
4198 /* XXX: specification say this is treated as a store by the MMU
4199 * but does not generate any exception
4200 */
79aceca5
FB
4201}
4202
4203/*** Segment register manipulation ***/
4204/* Supervisor only: */
4205/* mfsr */
4206GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
4207{
9a64fbe4 4208#if defined(CONFIG_USER_ONLY)
e1833e1f 4209 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4210#else
76a66253 4211 if (unlikely(!ctx->supervisor)) {
e1833e1f 4212 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4213 return;
9a64fbe4 4214 }
86c581dc 4215 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
76a66253 4216 gen_op_load_sr();
f78fb44e 4217 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
9a64fbe4 4218#endif
79aceca5
FB
4219}
4220
4221/* mfsrin */
9a64fbe4 4222GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
79aceca5 4223{
9a64fbe4 4224#if defined(CONFIG_USER_ONLY)
e1833e1f 4225 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4226#else
76a66253 4227 if (unlikely(!ctx->supervisor)) {
e1833e1f 4228 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4229 return;
9a64fbe4 4230 }
f78fb44e 4231 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4232 gen_op_srli_T1(28);
4233 gen_op_load_sr();
f78fb44e 4234 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
9a64fbe4 4235#endif
79aceca5
FB
4236}
4237
4238/* mtsr */
e63c59cb 4239GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
79aceca5 4240{
9a64fbe4 4241#if defined(CONFIG_USER_ONLY)
e1833e1f 4242 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4243#else
76a66253 4244 if (unlikely(!ctx->supervisor)) {
e1833e1f 4245 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4246 return;
9a64fbe4 4247 }
f78fb44e 4248 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4249 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
76a66253 4250 gen_op_store_sr();
9a64fbe4 4251#endif
79aceca5
FB
4252}
4253
4254/* mtsrin */
9a64fbe4 4255GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
79aceca5 4256{
9a64fbe4 4257#if defined(CONFIG_USER_ONLY)
e1833e1f 4258 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4259#else
76a66253 4260 if (unlikely(!ctx->supervisor)) {
e1833e1f 4261 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4262 return;
9a64fbe4 4263 }
f78fb44e
AJ
4264 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4265 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4266 gen_op_srli_T1(28);
4267 gen_op_store_sr();
9a64fbe4 4268#endif
79aceca5
FB
4269}
4270
12de9a39
JM
4271#if defined(TARGET_PPC64)
4272/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4273/* mfsr */
c7697e1f 4274GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
12de9a39
JM
4275{
4276#if defined(CONFIG_USER_ONLY)
4277 GEN_EXCP_PRIVREG(ctx);
4278#else
4279 if (unlikely(!ctx->supervisor)) {
4280 GEN_EXCP_PRIVREG(ctx);
4281 return;
4282 }
86c581dc 4283 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
12de9a39 4284 gen_op_load_slb();
f78fb44e 4285 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
12de9a39
JM
4286#endif
4287}
4288
4289/* mfsrin */
c7697e1f
JM
4290GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
4291 PPC_SEGMENT_64B)
12de9a39
JM
4292{
4293#if defined(CONFIG_USER_ONLY)
4294 GEN_EXCP_PRIVREG(ctx);
4295#else
4296 if (unlikely(!ctx->supervisor)) {
4297 GEN_EXCP_PRIVREG(ctx);
4298 return;
4299 }
f78fb44e 4300 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
12de9a39
JM
4301 gen_op_srli_T1(28);
4302 gen_op_load_slb();
f78fb44e 4303 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
12de9a39
JM
4304#endif
4305}
4306
4307/* mtsr */
c7697e1f 4308GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
12de9a39
JM
4309{
4310#if defined(CONFIG_USER_ONLY)
4311 GEN_EXCP_PRIVREG(ctx);
4312#else
4313 if (unlikely(!ctx->supervisor)) {
4314 GEN_EXCP_PRIVREG(ctx);
4315 return;
4316 }
f78fb44e 4317 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4318 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
12de9a39
JM
4319 gen_op_store_slb();
4320#endif
4321}
4322
4323/* mtsrin */
c7697e1f
JM
4324GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
4325 PPC_SEGMENT_64B)
12de9a39
JM
4326{
4327#if defined(CONFIG_USER_ONLY)
4328 GEN_EXCP_PRIVREG(ctx);
4329#else
4330 if (unlikely(!ctx->supervisor)) {
4331 GEN_EXCP_PRIVREG(ctx);
4332 return;
4333 }
f78fb44e
AJ
4334 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4335 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
12de9a39
JM
4336 gen_op_srli_T1(28);
4337 gen_op_store_slb();
4338#endif
4339}
4340#endif /* defined(TARGET_PPC64) */
4341
79aceca5
FB
4342/*** Lookaside buffer management ***/
4343/* Optional & supervisor only: */
4344/* tlbia */
3fc6c082 4345GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
79aceca5 4346{
9a64fbe4 4347#if defined(CONFIG_USER_ONLY)
e1833e1f 4348 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4349#else
76a66253 4350 if (unlikely(!ctx->supervisor)) {
e1833e1f 4351 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4352 return;
9a64fbe4
FB
4353 }
4354 gen_op_tlbia();
4355#endif
79aceca5
FB
4356}
4357
4358/* tlbie */
76a66253 4359GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
79aceca5 4360{
9a64fbe4 4361#if defined(CONFIG_USER_ONLY)
e1833e1f 4362 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4363#else
76a66253 4364 if (unlikely(!ctx->supervisor)) {
e1833e1f 4365 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4366 return;
9a64fbe4 4367 }
f78fb44e 4368 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
d9bce9d9
JM
4369#if defined(TARGET_PPC64)
4370 if (ctx->sf_mode)
4371 gen_op_tlbie_64();
4372 else
4373#endif
4374 gen_op_tlbie();
9a64fbe4 4375#endif
79aceca5
FB
4376}
4377
4378/* tlbsync */
76a66253 4379GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
79aceca5 4380{
9a64fbe4 4381#if defined(CONFIG_USER_ONLY)
e1833e1f 4382 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4383#else
76a66253 4384 if (unlikely(!ctx->supervisor)) {
e1833e1f 4385 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4386 return;
9a64fbe4
FB
4387 }
4388 /* This has no effect: it should ensure that all previous
4389 * tlbie have completed
4390 */
e1833e1f 4391 GEN_STOP(ctx);
9a64fbe4 4392#endif
79aceca5
FB
4393}
4394
426613db
JM
4395#if defined(TARGET_PPC64)
4396/* slbia */
4397GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4398{
4399#if defined(CONFIG_USER_ONLY)
e1833e1f 4400 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4401#else
4402 if (unlikely(!ctx->supervisor)) {
e1833e1f 4403 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4404 return;
4405 }
4406 gen_op_slbia();
426613db
JM
4407#endif
4408}
4409
4410/* slbie */
4411GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4412{
4413#if defined(CONFIG_USER_ONLY)
e1833e1f 4414 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4415#else
4416 if (unlikely(!ctx->supervisor)) {
e1833e1f 4417 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4418 return;
4419 }
f78fb44e 4420 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
426613db 4421 gen_op_slbie();
426613db
JM
4422#endif
4423}
4424#endif
4425
79aceca5
FB
4426/*** External control ***/
4427/* Optional: */
111bfab3 4428/* eciwx */
79aceca5
FB
4429GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4430{
fa407c03
AJ
4431 /* Should check EAR[E] ! */
4432 TCGv t0 = tcg_temp_new();
a7859e89 4433 gen_set_access_type(ACCESS_RES);
fa407c03
AJ
4434 gen_addr_reg_index(t0, ctx);
4435 gen_check_align(ctx, t0, 0x03);
4436 gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx);
4437 tcg_temp_free(t0);
76a66253
JM
4438}
4439
4440/* ecowx */
4441GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4442{
fa407c03
AJ
4443 /* Should check EAR[E] ! */
4444 TCGv t0 = tcg_temp_new();
4445 gen_set_access_type(ACCESS_RES);
4446 gen_addr_reg_index(t0, ctx);
4447 gen_check_align(ctx, t0, 0x03);
4448 gen_qemu_st32(cpu_gpr[rD(ctx->opcode)], t0, ctx->mem_idx);
4449 tcg_temp_free(t0);
76a66253
JM
4450}
4451
4452/* PowerPC 601 specific instructions */
4453/* abs - abs. */
4454GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4455{
22e0e173
AJ
4456 int l1 = gen_new_label();
4457 int l2 = gen_new_label();
4458 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l1);
4459 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4460 tcg_gen_br(l2);
4461 gen_set_label(l1);
4462 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4463 gen_set_label(l2);
76a66253 4464 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4465 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4466}
4467
4468/* abso - abso. */
4469GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4470{
22e0e173
AJ
4471 int l1 = gen_new_label();
4472 int l2 = gen_new_label();
4473 int l3 = gen_new_label();
4474 /* Start with XER OV disabled, the most likely case */
4475 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4476 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rA(ctx->opcode)], 0, l2);
4477 tcg_gen_brcondi_tl(TCG_COND_NE, cpu_gpr[rA(ctx->opcode)], 0x80000000, l1);
4478 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4479 tcg_gen_br(l2);
4480 gen_set_label(l1);
4481 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4482 tcg_gen_br(l3);
4483 gen_set_label(l2);
4484 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4485 gen_set_label(l3);
76a66253 4486 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4487 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4488}
4489
4490/* clcs */
a750fc0b 4491GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
76a66253 4492{
22e0e173
AJ
4493 TCGv_i32 t0 = tcg_const_i32(rA(ctx->opcode));
4494 gen_helper_clcs(cpu_gpr[rD(ctx->opcode)], t0);
4495 tcg_temp_free_i32(t0);
c7697e1f 4496 /* Rc=1 sets CR0 to an undefined state */
76a66253
JM
4497}
4498
4499/* div - div. */
4500GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4501{
22e0e173 4502 gen_helper_div(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4503 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4504 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4505}
4506
4507/* divo - divo. */
4508GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4509{
22e0e173 4510 gen_helper_divo(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4511 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4512 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4513}
4514
4515/* divs - divs. */
4516GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4517{
22e0e173 4518 gen_helper_divs(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4519 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4520 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4521}
4522
4523/* divso - divso. */
4524GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4525{
22e0e173 4526 gen_helper_divso(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
76a66253 4527 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4528 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4529}
4530
4531/* doz - doz. */
4532GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4533{
22e0e173
AJ
4534 int l1 = gen_new_label();
4535 int l2 = gen_new_label();
4536 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4537 tcg_gen_sub_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4538 tcg_gen_br(l2);
4539 gen_set_label(l1);
4540 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4541 gen_set_label(l2);
76a66253 4542 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4543 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4544}
4545
4546/* dozo - dozo. */
4547GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4548{
22e0e173
AJ
4549 int l1 = gen_new_label();
4550 int l2 = gen_new_label();
4551 TCGv t0 = tcg_temp_new();
4552 TCGv t1 = tcg_temp_new();
4553 TCGv t2 = tcg_temp_new();
4554 /* Start with XER OV disabled, the most likely case */
4555 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4556 tcg_gen_brcond_tl(TCG_COND_GE, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], l1);
4557 tcg_gen_sub_tl(t0, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4558 tcg_gen_xor_tl(t1, cpu_gpr[rB(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4559 tcg_gen_xor_tl(t2, cpu_gpr[rA(ctx->opcode)], t0);
4560 tcg_gen_andc_tl(t1, t1, t2);
4561 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
4562 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4563 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4564 tcg_gen_br(l2);
4565 gen_set_label(l1);
4566 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4567 gen_set_label(l2);
4568 tcg_temp_free(t0);
4569 tcg_temp_free(t1);
4570 tcg_temp_free(t2);
76a66253 4571 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4572 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4573}
4574
4575/* dozi */
4576GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4577{
22e0e173
AJ
4578 target_long simm = SIMM(ctx->opcode);
4579 int l1 = gen_new_label();
4580 int l2 = gen_new_label();
4581 tcg_gen_brcondi_tl(TCG_COND_LT, cpu_gpr[rA(ctx->opcode)], simm, l1);
4582 tcg_gen_subfi_tl(cpu_gpr[rD(ctx->opcode)], simm, cpu_gpr[rA(ctx->opcode)]);
4583 tcg_gen_br(l2);
4584 gen_set_label(l1);
4585 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], 0);
4586 gen_set_label(l2);
4587 if (unlikely(Rc(ctx->opcode) != 0))
4588 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4589}
4590
76a66253
JM
4591/* lscbx - lscbx. */
4592GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4593{
bdb4b689
AJ
4594 TCGv t0 = tcg_temp_new();
4595 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
4596 TCGv_i32 t2 = tcg_const_i32(rA(ctx->opcode));
4597 TCGv_i32 t3 = tcg_const_i32(rB(ctx->opcode));
76a66253 4598
bdb4b689 4599 gen_addr_reg_index(t0, ctx);
76a66253 4600 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4601 gen_update_nip(ctx, ctx->nip - 4);
bdb4b689
AJ
4602 gen_helper_lscbx(t0, t0, t1, t2, t3);
4603 tcg_temp_free_i32(t1);
4604 tcg_temp_free_i32(t2);
4605 tcg_temp_free_i32(t3);
3d7b417e 4606 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
bdb4b689 4607 tcg_gen_or_tl(cpu_xer, cpu_xer, t0);
76a66253 4608 if (unlikely(Rc(ctx->opcode) != 0))
bdb4b689
AJ
4609 gen_set_Rc0(ctx, t0);
4610 tcg_temp_free(t0);
76a66253
JM
4611}
4612
4613/* maskg - maskg. */
4614GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4615{
22e0e173
AJ
4616 int l1 = gen_new_label();
4617 TCGv t0 = tcg_temp_new();
4618 TCGv t1 = tcg_temp_new();
4619 TCGv t2 = tcg_temp_new();
4620 TCGv t3 = tcg_temp_new();
4621 tcg_gen_movi_tl(t3, 0xFFFFFFFF);
4622 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4623 tcg_gen_andi_tl(t1, cpu_gpr[rS(ctx->opcode)], 0x1F);
4624 tcg_gen_addi_tl(t2, t0, 1);
4625 tcg_gen_shr_tl(t2, t3, t2);
4626 tcg_gen_shr_tl(t3, t3, t1);
4627 tcg_gen_xor_tl(cpu_gpr[rA(ctx->opcode)], t2, t3);
4628 tcg_gen_brcond_tl(TCG_COND_GE, t0, t1, l1);
4629 tcg_gen_neg_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4630 gen_set_label(l1);
4631 tcg_temp_free(t0);
4632 tcg_temp_free(t1);
4633 tcg_temp_free(t2);
4634 tcg_temp_free(t3);
76a66253 4635 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4636 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4637}
4638
4639/* maskir - maskir. */
4640GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4641{
22e0e173
AJ
4642 TCGv t0 = tcg_temp_new();
4643 TCGv t1 = tcg_temp_new();
4644 tcg_gen_and_tl(t0, cpu_gpr[rS(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4645 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
4646 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4647 tcg_temp_free(t0);
4648 tcg_temp_free(t1);
76a66253 4649 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4650 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4651}
4652
4653/* mul - mul. */
4654GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4655{
22e0e173
AJ
4656 TCGv_i64 t0 = tcg_temp_new_i64();
4657 TCGv_i64 t1 = tcg_temp_new_i64();
4658 TCGv t2 = tcg_temp_new();
4659 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4660 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4661 tcg_gen_mul_i64(t0, t0, t1);
4662 tcg_gen_trunc_i64_tl(t2, t0);
4663 gen_store_spr(SPR_MQ, t2);
4664 tcg_gen_shri_i64(t1, t0, 32);
4665 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4666 tcg_temp_free_i64(t0);
4667 tcg_temp_free_i64(t1);
4668 tcg_temp_free(t2);
76a66253 4669 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4670 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4671}
4672
4673/* mulo - mulo. */
4674GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4675{
22e0e173
AJ
4676 int l1 = gen_new_label();
4677 TCGv_i64 t0 = tcg_temp_new_i64();
4678 TCGv_i64 t1 = tcg_temp_new_i64();
4679 TCGv t2 = tcg_temp_new();
4680 /* Start with XER OV disabled, the most likely case */
4681 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
4682 tcg_gen_extu_tl_i64(t0, cpu_gpr[rA(ctx->opcode)]);
4683 tcg_gen_extu_tl_i64(t1, cpu_gpr[rB(ctx->opcode)]);
4684 tcg_gen_mul_i64(t0, t0, t1);
4685 tcg_gen_trunc_i64_tl(t2, t0);
4686 gen_store_spr(SPR_MQ, t2);
4687 tcg_gen_shri_i64(t1, t0, 32);
4688 tcg_gen_trunc_i64_tl(cpu_gpr[rD(ctx->opcode)], t1);
4689 tcg_gen_ext32s_i64(t1, t0);
4690 tcg_gen_brcond_i64(TCG_COND_EQ, t0, t1, l1);
4691 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
4692 gen_set_label(l1);
4693 tcg_temp_free_i64(t0);
4694 tcg_temp_free_i64(t1);
4695 tcg_temp_free(t2);
76a66253 4696 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4697 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4698}
4699
4700/* nabs - nabs. */
4701GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4702{
22e0e173
AJ
4703 int l1 = gen_new_label();
4704 int l2 = gen_new_label();
4705 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4706 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4707 tcg_gen_br(l2);
4708 gen_set_label(l1);
4709 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4710 gen_set_label(l2);
76a66253 4711 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4712 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4713}
4714
4715/* nabso - nabso. */
4716GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4717{
22e0e173
AJ
4718 int l1 = gen_new_label();
4719 int l2 = gen_new_label();
4720 tcg_gen_brcondi_tl(TCG_COND_GT, cpu_gpr[rA(ctx->opcode)], 0, l1);
4721 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4722 tcg_gen_br(l2);
4723 gen_set_label(l1);
4724 tcg_gen_neg_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
4725 gen_set_label(l2);
4726 /* nabs never overflows */
4727 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
76a66253 4728 if (unlikely(Rc(ctx->opcode) != 0))
22e0e173 4729 gen_set_Rc0(ctx, cpu_gpr[rD(ctx->opcode)]);
76a66253
JM
4730}
4731
4732/* rlmi - rlmi. */
4733GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4734{
7487953d
AJ
4735 uint32_t mb = MB(ctx->opcode);
4736 uint32_t me = ME(ctx->opcode);
4737 TCGv t0 = tcg_temp_new();
4738 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4739 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4740 tcg_gen_andi_tl(t0, t0, MASK(mb, me));
4741 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~MASK(mb, me));
4742 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], t0);
4743 tcg_temp_free(t0);
76a66253 4744 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4745 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4746}
4747
4748/* rrib - rrib. */
4749GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4750{
7487953d
AJ
4751 TCGv t0 = tcg_temp_new();
4752 TCGv t1 = tcg_temp_new();
4753 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4754 tcg_gen_movi_tl(t1, 0x80000000);
4755 tcg_gen_shr_tl(t1, t1, t0);
4756 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4757 tcg_gen_and_tl(t0, t0, t1);
4758 tcg_gen_andc_tl(t1, cpu_gpr[rA(ctx->opcode)], t1);
4759 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4760 tcg_temp_free(t0);
4761 tcg_temp_free(t1);
76a66253 4762 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4763 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4764}
4765
4766/* sle - sle. */
4767GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4768{
7487953d
AJ
4769 TCGv t0 = tcg_temp_new();
4770 TCGv t1 = tcg_temp_new();
4771 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4772 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4773 tcg_gen_subfi_tl(t1, 32, t1);
4774 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4775 tcg_gen_or_tl(t1, t0, t1);
4776 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4777 gen_store_spr(SPR_MQ, t1);
4778 tcg_temp_free(t0);
4779 tcg_temp_free(t1);
76a66253 4780 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4781 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4782}
4783
4784/* sleq - sleq. */
4785GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4786{
7487953d
AJ
4787 TCGv t0 = tcg_temp_new();
4788 TCGv t1 = tcg_temp_new();
4789 TCGv t2 = tcg_temp_new();
4790 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4791 tcg_gen_movi_tl(t2, 0xFFFFFFFF);
4792 tcg_gen_shl_tl(t2, t2, t0);
4793 tcg_gen_rotl_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4794 gen_load_spr(t1, SPR_MQ);
4795 gen_store_spr(SPR_MQ, t0);
4796 tcg_gen_and_tl(t0, t0, t2);
4797 tcg_gen_andc_tl(t1, t1, t2);
4798 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4799 tcg_temp_free(t0);
4800 tcg_temp_free(t1);
4801 tcg_temp_free(t2);
76a66253 4802 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4803 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4804}
4805
4806/* sliq - sliq. */
4807GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4808{
7487953d
AJ
4809 int sh = SH(ctx->opcode);
4810 TCGv t0 = tcg_temp_new();
4811 TCGv t1 = tcg_temp_new();
4812 tcg_gen_shli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4813 tcg_gen_shri_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4814 tcg_gen_or_tl(t1, t0, t1);
4815 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4816 gen_store_spr(SPR_MQ, t1);
4817 tcg_temp_free(t0);
4818 tcg_temp_free(t1);
76a66253 4819 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4820 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4821}
4822
4823/* slliq - slliq. */
4824GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4825{
7487953d
AJ
4826 int sh = SH(ctx->opcode);
4827 TCGv t0 = tcg_temp_new();
4828 TCGv t1 = tcg_temp_new();
4829 tcg_gen_rotli_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4830 gen_load_spr(t1, SPR_MQ);
4831 gen_store_spr(SPR_MQ, t0);
4832 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU << sh));
4833 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU << sh));
4834 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4835 tcg_temp_free(t0);
4836 tcg_temp_free(t1);
76a66253 4837 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4838 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4839}
4840
4841/* sllq - sllq. */
4842GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4843{
7487953d
AJ
4844 int l1 = gen_new_label();
4845 int l2 = gen_new_label();
4846 TCGv t0 = tcg_temp_local_new();
4847 TCGv t1 = tcg_temp_local_new();
4848 TCGv t2 = tcg_temp_local_new();
4849 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4850 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4851 tcg_gen_shl_tl(t1, t1, t2);
4852 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4853 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
4854 gen_load_spr(t0, SPR_MQ);
4855 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4856 tcg_gen_br(l2);
4857 gen_set_label(l1);
4858 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4859 gen_load_spr(t2, SPR_MQ);
4860 tcg_gen_andc_tl(t1, t2, t1);
4861 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
4862 gen_set_label(l2);
4863 tcg_temp_free(t0);
4864 tcg_temp_free(t1);
4865 tcg_temp_free(t2);
76a66253 4866 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4867 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4868}
4869
4870/* slq - slq. */
4871GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4872{
7487953d
AJ
4873 int l1 = gen_new_label();
4874 TCGv t0 = tcg_temp_new();
4875 TCGv t1 = tcg_temp_new();
4876 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4877 tcg_gen_shl_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4878 tcg_gen_subfi_tl(t1, 32, t1);
4879 tcg_gen_shr_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4880 tcg_gen_or_tl(t1, t0, t1);
4881 gen_store_spr(SPR_MQ, t1);
4882 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
4883 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4884 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4885 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
4886 gen_set_label(l1);
4887 tcg_temp_free(t0);
4888 tcg_temp_free(t1);
76a66253 4889 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4890 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4891}
4892
d9bce9d9 4893/* sraiq - sraiq. */
76a66253
JM
4894GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4895{
7487953d
AJ
4896 int sh = SH(ctx->opcode);
4897 int l1 = gen_new_label();
4898 TCGv t0 = tcg_temp_new();
4899 TCGv t1 = tcg_temp_new();
4900 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
4901 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
4902 tcg_gen_or_tl(t0, t0, t1);
4903 gen_store_spr(SPR_MQ, t0);
4904 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4905 tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1);
4906 tcg_gen_brcondi_tl(TCG_COND_GE, cpu_gpr[rS(ctx->opcode)], 0, l1);
4907 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4908 gen_set_label(l1);
4909 tcg_gen_sari_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], sh);
4910 tcg_temp_free(t0);
4911 tcg_temp_free(t1);
76a66253 4912 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4913 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4914}
4915
4916/* sraq - sraq. */
4917GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4918{
7487953d
AJ
4919 int l1 = gen_new_label();
4920 int l2 = gen_new_label();
4921 TCGv t0 = tcg_temp_new();
4922 TCGv t1 = tcg_temp_local_new();
4923 TCGv t2 = tcg_temp_local_new();
4924 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
4925 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
4926 tcg_gen_sar_tl(t1, cpu_gpr[rS(ctx->opcode)], t2);
4927 tcg_gen_subfi_tl(t2, 32, t2);
4928 tcg_gen_shl_tl(t2, cpu_gpr[rS(ctx->opcode)], t2);
4929 tcg_gen_or_tl(t0, t0, t2);
4930 gen_store_spr(SPR_MQ, t0);
4931 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
4932 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l1);
4933 tcg_gen_mov_tl(t2, cpu_gpr[rS(ctx->opcode)]);
4934 tcg_gen_sari_tl(t1, cpu_gpr[rS(ctx->opcode)], 31);
4935 gen_set_label(l1);
4936 tcg_temp_free(t0);
4937 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t1);
4938 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_CA));
4939 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l2);
4940 tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, l2);
4941 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_CA));
4942 gen_set_label(l2);
4943 tcg_temp_free(t1);
4944 tcg_temp_free(t2);
76a66253 4945 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4946 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4947}
4948
4949/* sre - sre. */
4950GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4951{
7487953d
AJ
4952 TCGv t0 = tcg_temp_new();
4953 TCGv t1 = tcg_temp_new();
4954 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4955 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4956 tcg_gen_subfi_tl(t1, 32, t1);
4957 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
4958 tcg_gen_or_tl(t1, t0, t1);
4959 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
4960 gen_store_spr(SPR_MQ, t1);
4961 tcg_temp_free(t0);
4962 tcg_temp_free(t1);
76a66253 4963 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4964 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4965}
4966
4967/* srea - srea. */
4968GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4969{
7487953d
AJ
4970 TCGv t0 = tcg_temp_new();
4971 TCGv t1 = tcg_temp_new();
4972 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
4973 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
4974 gen_store_spr(SPR_MQ, t0);
4975 tcg_gen_sar_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)], t1);
4976 tcg_temp_free(t0);
4977 tcg_temp_free(t1);
76a66253 4978 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 4979 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
4980}
4981
4982/* sreq */
4983GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4984{
7487953d
AJ
4985 TCGv t0 = tcg_temp_new();
4986 TCGv t1 = tcg_temp_new();
4987 TCGv t2 = tcg_temp_new();
4988 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x1F);
4989 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
4990 tcg_gen_shr_tl(t1, t1, t0);
4991 tcg_gen_rotr_tl(t0, cpu_gpr[rS(ctx->opcode)], t0);
4992 gen_load_spr(t2, SPR_MQ);
4993 gen_store_spr(SPR_MQ, t0);
4994 tcg_gen_and_tl(t0, t0, t1);
4995 tcg_gen_andc_tl(t2, t2, t1);
4996 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
4997 tcg_temp_free(t0);
4998 tcg_temp_free(t1);
4999 tcg_temp_free(t2);
76a66253 5000 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5001 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5002}
5003
5004/* sriq */
5005GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
5006{
7487953d
AJ
5007 int sh = SH(ctx->opcode);
5008 TCGv t0 = tcg_temp_new();
5009 TCGv t1 = tcg_temp_new();
5010 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5011 tcg_gen_shli_tl(t1, cpu_gpr[rS(ctx->opcode)], 32 - sh);
5012 tcg_gen_or_tl(t1, t0, t1);
5013 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5014 gen_store_spr(SPR_MQ, t1);
5015 tcg_temp_free(t0);
5016 tcg_temp_free(t1);
76a66253 5017 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5018 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5019}
5020
5021/* srliq */
5022GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
5023{
7487953d
AJ
5024 int sh = SH(ctx->opcode);
5025 TCGv t0 = tcg_temp_new();
5026 TCGv t1 = tcg_temp_new();
5027 tcg_gen_rotri_tl(t0, cpu_gpr[rS(ctx->opcode)], sh);
5028 gen_load_spr(t1, SPR_MQ);
5029 gen_store_spr(SPR_MQ, t0);
5030 tcg_gen_andi_tl(t0, t0, (0xFFFFFFFFU >> sh));
5031 tcg_gen_andi_tl(t1, t1, ~(0xFFFFFFFFU >> sh));
5032 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5033 tcg_temp_free(t0);
5034 tcg_temp_free(t1);
76a66253 5035 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5036 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5037}
5038
5039/* srlq */
5040GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
5041{
7487953d
AJ
5042 int l1 = gen_new_label();
5043 int l2 = gen_new_label();
5044 TCGv t0 = tcg_temp_local_new();
5045 TCGv t1 = tcg_temp_local_new();
5046 TCGv t2 = tcg_temp_local_new();
5047 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x1F);
5048 tcg_gen_movi_tl(t1, 0xFFFFFFFF);
5049 tcg_gen_shr_tl(t2, t1, t2);
5050 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x20);
5051 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5052 gen_load_spr(t0, SPR_MQ);
5053 tcg_gen_and_tl(cpu_gpr[rA(ctx->opcode)], t0, t2);
5054 tcg_gen_br(l2);
5055 gen_set_label(l1);
5056 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t2);
5057 tcg_gen_and_tl(t0, t0, t2);
5058 gen_load_spr(t1, SPR_MQ);
5059 tcg_gen_andc_tl(t1, t1, t2);
5060 tcg_gen_or_tl(cpu_gpr[rA(ctx->opcode)], t0, t1);
5061 gen_set_label(l2);
5062 tcg_temp_free(t0);
5063 tcg_temp_free(t1);
5064 tcg_temp_free(t2);
76a66253 5065 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5066 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5067}
5068
5069/* srq */
5070GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
5071{
7487953d
AJ
5072 int l1 = gen_new_label();
5073 TCGv t0 = tcg_temp_new();
5074 TCGv t1 = tcg_temp_new();
5075 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x1F);
5076 tcg_gen_shr_tl(t0, cpu_gpr[rS(ctx->opcode)], t1);
5077 tcg_gen_subfi_tl(t1, 32, t1);
5078 tcg_gen_shl_tl(t1, cpu_gpr[rS(ctx->opcode)], t1);
5079 tcg_gen_or_tl(t1, t0, t1);
5080 gen_store_spr(SPR_MQ, t1);
5081 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0x20);
5082 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], t0);
5083 tcg_gen_brcondi_tl(TCG_COND_EQ, t0, 0, l1);
5084 tcg_gen_movi_tl(cpu_gpr[rA(ctx->opcode)], 0);
5085 gen_set_label(l1);
5086 tcg_temp_free(t0);
5087 tcg_temp_free(t1);
76a66253 5088 if (unlikely(Rc(ctx->opcode) != 0))
7487953d 5089 gen_set_Rc0(ctx, cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5090}
5091
5092/* PowerPC 602 specific instructions */
5093/* dsa */
5094GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
5095{
5096 /* XXX: TODO */
e1833e1f 5097 GEN_EXCP_INVAL(ctx);
76a66253
JM
5098}
5099
5100/* esa */
5101GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
5102{
5103 /* XXX: TODO */
e1833e1f 5104 GEN_EXCP_INVAL(ctx);
76a66253
JM
5105}
5106
5107/* mfrom */
5108GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
5109{
5110#if defined(CONFIG_USER_ONLY)
e1833e1f 5111 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5112#else
5113 if (unlikely(!ctx->supervisor)) {
e1833e1f 5114 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5115 return;
5116 }
cf02a65c 5117 gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
76a66253
JM
5118#endif
5119}
5120
5121/* 602 - 603 - G2 TLB management */
5122/* tlbld */
c7697e1f 5123GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
5124{
5125#if defined(CONFIG_USER_ONLY)
e1833e1f 5126 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5127#else
5128 if (unlikely(!ctx->supervisor)) {
e1833e1f 5129 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5130 return;
5131 }
0f3955e2 5132 gen_helper_load_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5133#endif
5134}
5135
5136/* tlbli */
c7697e1f 5137GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
5138{
5139#if defined(CONFIG_USER_ONLY)
e1833e1f 5140 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5141#else
5142 if (unlikely(!ctx->supervisor)) {
e1833e1f 5143 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5144 return;
5145 }
0f3955e2 5146 gen_helper_load_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
5147#endif
5148}
5149
7dbe11ac
JM
5150/* 74xx TLB management */
5151/* tlbld */
c7697e1f 5152GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
5153{
5154#if defined(CONFIG_USER_ONLY)
5155 GEN_EXCP_PRIVOPC(ctx);
5156#else
5157 if (unlikely(!ctx->supervisor)) {
5158 GEN_EXCP_PRIVOPC(ctx);
5159 return;
5160 }
0f3955e2 5161 gen_helper_load_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5162#endif
5163}
5164
5165/* tlbli */
c7697e1f 5166GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
5167{
5168#if defined(CONFIG_USER_ONLY)
5169 GEN_EXCP_PRIVOPC(ctx);
5170#else
5171 if (unlikely(!ctx->supervisor)) {
5172 GEN_EXCP_PRIVOPC(ctx);
5173 return;
5174 }
0f3955e2 5175 gen_helper_load_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5176#endif
5177}
5178
76a66253
JM
5179/* POWER instructions not in PowerPC 601 */
5180/* clf */
5181GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
5182{
5183 /* Cache line flush: implemented as no-op */
5184}
5185
5186/* cli */
5187GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
5188{
7f75ffd3 5189 /* Cache line invalidate: privileged and treated as no-op */
76a66253 5190#if defined(CONFIG_USER_ONLY)
e1833e1f 5191 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5192#else
5193 if (unlikely(!ctx->supervisor)) {
e1833e1f 5194 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5195 return;
5196 }
5197#endif
5198}
5199
5200/* dclst */
5201GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
5202{
5203 /* Data cache line store: treated as no-op */
5204}
5205
5206GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
5207{
5208#if defined(CONFIG_USER_ONLY)
e1833e1f 5209 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5210#else
5211 if (unlikely(!ctx->supervisor)) {
e1833e1f 5212 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5213 return;
5214 }
5215 int ra = rA(ctx->opcode);
5216 int rd = rD(ctx->opcode);
5217
e2be8d8d 5218 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5219 gen_op_POWER_mfsri();
f78fb44e 5220 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
76a66253 5221 if (ra != 0 && ra != rd)
f78fb44e 5222 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
76a66253
JM
5223#endif
5224}
5225
5226GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5227{
5228#if defined(CONFIG_USER_ONLY)
e1833e1f 5229 GEN_EXCP_PRIVOPC(ctx);
76a66253 5230#else
22e0e173 5231 TCGv t0;
76a66253 5232 if (unlikely(!ctx->supervisor)) {
e1833e1f 5233 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5234 return;
5235 }
22e0e173
AJ
5236 t0 = tcg_temp_new();
5237 gen_addr_reg_index(t0, ctx);
5238 gen_helper_rac(cpu_gpr[rD(ctx->opcode)], t0);
5239 tcg_temp_free(t0);
76a66253
JM
5240#endif
5241}
5242
5243GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
5244{
5245#if defined(CONFIG_USER_ONLY)
e1833e1f 5246 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5247#else
5248 if (unlikely(!ctx->supervisor)) {
e1833e1f 5249 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5250 return;
5251 }
d72a19f7 5252 gen_helper_rfsvc();
e1833e1f 5253 GEN_SYNC(ctx);
76a66253
JM
5254#endif
5255}
5256
5257/* svc is not implemented for now */
5258
5259/* POWER2 specific instructions */
5260/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5261
5262/* lfq */
5263GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5264{
01a4afeb
AJ
5265 int rd = rD(ctx->opcode);
5266 TCGv t0 = tcg_temp_new();
5267 gen_addr_imm_index(t0, ctx, 0);
5268 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5269 tcg_gen_addi_tl(t0, t0, 8);
5270 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5271 tcg_temp_free(t0);
76a66253
JM
5272}
5273
5274/* lfqu */
5275GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5276{
5277 int ra = rA(ctx->opcode);
01a4afeb
AJ
5278 int rd = rD(ctx->opcode);
5279 TCGv t0 = tcg_temp_new();
5280 TCGv t1 = tcg_temp_new();
5281 gen_addr_imm_index(t0, ctx, 0);
5282 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5283 tcg_gen_addi_tl(t1, t0, 8);
5284 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5285 if (ra != 0)
01a4afeb
AJ
5286 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5287 tcg_temp_free(t0);
5288 tcg_temp_free(t1);
76a66253
JM
5289}
5290
5291/* lfqux */
5292GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
5293{
5294 int ra = rA(ctx->opcode);
01a4afeb
AJ
5295 int rd = rD(ctx->opcode);
5296 TCGv t0 = tcg_temp_new();
5297 TCGv t1 = tcg_temp_new();
5298 gen_addr_reg_index(t0, ctx);
5299 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5300 tcg_gen_addi_tl(t1, t0, 8);
5301 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5302 if (ra != 0)
01a4afeb
AJ
5303 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5304 tcg_temp_free(t0);
5305 tcg_temp_free(t1);
76a66253
JM
5306}
5307
5308/* lfqx */
5309GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
5310{
01a4afeb
AJ
5311 int rd = rD(ctx->opcode);
5312 TCGv t0 = tcg_temp_new();
5313 gen_addr_reg_index(t0, ctx);
5314 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5315 tcg_gen_addi_tl(t0, t0, 8);
5316 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5317 tcg_temp_free(t0);
76a66253
JM
5318}
5319
5320/* stfq */
5321GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5322{
01a4afeb
AJ
5323 int rd = rD(ctx->opcode);
5324 TCGv t0 = tcg_temp_new();
5325 gen_addr_imm_index(t0, ctx, 0);
5326 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5327 tcg_gen_addi_tl(t0, t0, 8);
5328 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5329 tcg_temp_free(t0);
76a66253
JM
5330}
5331
5332/* stfqu */
5333GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5334{
5335 int ra = rA(ctx->opcode);
01a4afeb
AJ
5336 int rd = rD(ctx->opcode);
5337 TCGv t0 = tcg_temp_new();
5338 TCGv t1 = tcg_temp_new();
5339 gen_addr_imm_index(t0, ctx, 0);
5340 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5341 tcg_gen_addi_tl(t1, t0, 8);
5342 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5343 if (ra != 0)
01a4afeb
AJ
5344 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5345 tcg_temp_free(t0);
5346 tcg_temp_free(t1);
76a66253
JM
5347}
5348
5349/* stfqux */
5350GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
5351{
5352 int ra = rA(ctx->opcode);
01a4afeb
AJ
5353 int rd = rD(ctx->opcode);
5354 TCGv t0 = tcg_temp_new();
5355 TCGv t1 = tcg_temp_new();
5356 gen_addr_reg_index(t0, ctx);
5357 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5358 tcg_gen_addi_tl(t1, t0, 8);
5359 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5360 if (ra != 0)
01a4afeb
AJ
5361 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5362 tcg_temp_free(t0);
5363 tcg_temp_free(t1);
76a66253
JM
5364}
5365
5366/* stfqx */
5367GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
5368{
01a4afeb
AJ
5369 int rd = rD(ctx->opcode);
5370 TCGv t0 = tcg_temp_new();
5371 gen_addr_reg_index(t0, ctx);
5372 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5373 tcg_gen_addi_tl(t0, t0, 8);
5374 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5375 tcg_temp_free(t0);
76a66253
JM
5376}
5377
5378/* BookE specific instructions */
2662a059 5379/* XXX: not implemented on 440 ? */
05332d70 5380GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
76a66253
JM
5381{
5382 /* XXX: TODO */
e1833e1f 5383 GEN_EXCP_INVAL(ctx);
76a66253
JM
5384}
5385
2662a059 5386/* XXX: not implemented on 440 ? */
05332d70 5387GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
76a66253
JM
5388{
5389#if defined(CONFIG_USER_ONLY)
e1833e1f 5390 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5391#else
5392 if (unlikely(!ctx->supervisor)) {
e1833e1f 5393 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5394 return;
5395 }
e2be8d8d 5396 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5397 /* Use the same micro-ops as for tlbie */
d9bce9d9
JM
5398#if defined(TARGET_PPC64)
5399 if (ctx->sf_mode)
5400 gen_op_tlbie_64();
5401 else
5402#endif
5403 gen_op_tlbie();
76a66253
JM
5404#endif
5405}
5406
5407/* All 405 MAC instructions are translated here */
b068d6a7
JM
5408static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5409 int opc2, int opc3,
5410 int ra, int rb, int rt, int Rc)
76a66253 5411{
182608d4
AJ
5412 TCGv t0, t1;
5413
a7812ae4
PB
5414 t0 = tcg_temp_local_new();
5415 t1 = tcg_temp_local_new();
182608d4 5416
76a66253
JM
5417 switch (opc3 & 0x0D) {
5418 case 0x05:
5419 /* macchw - macchw. - macchwo - macchwo. */
5420 /* macchws - macchws. - macchwso - macchwso. */
5421 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5422 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5423 /* mulchw - mulchw. */
182608d4
AJ
5424 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5425 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5426 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5427 break;
5428 case 0x04:
5429 /* macchwu - macchwu. - macchwuo - macchwuo. */
5430 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5431 /* mulchwu - mulchwu. */
182608d4
AJ
5432 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5433 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5434 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5435 break;
5436 case 0x01:
5437 /* machhw - machhw. - machhwo - machhwo. */
5438 /* machhws - machhws. - machhwso - machhwso. */
5439 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5440 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5441 /* mulhhw - mulhhw. */
182608d4
AJ
5442 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5443 tcg_gen_ext16s_tl(t0, t0);
5444 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5445 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5446 break;
5447 case 0x00:
5448 /* machhwu - machhwu. - machhwuo - machhwuo. */
5449 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5450 /* mulhhwu - mulhhwu. */
182608d4
AJ
5451 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5452 tcg_gen_ext16u_tl(t0, t0);
5453 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5454 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5455 break;
5456 case 0x0D:
5457 /* maclhw - maclhw. - maclhwo - maclhwo. */
5458 /* maclhws - maclhws. - maclhwso - maclhwso. */
5459 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5460 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5461 /* mullhw - mullhw. */
182608d4
AJ
5462 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5463 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5464 break;
5465 case 0x0C:
5466 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5467 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5468 /* mullhwu - mullhwu. */
182608d4
AJ
5469 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5470 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5471 break;
5472 }
76a66253 5473 if (opc2 & 0x04) {
182608d4
AJ
5474 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5475 tcg_gen_mul_tl(t1, t0, t1);
5476 if (opc2 & 0x02) {
5477 /* nmultiply-and-accumulate (0x0E) */
5478 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5479 } else {
5480 /* multiply-and-accumulate (0x0C) */
5481 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5482 }
5483
5484 if (opc3 & 0x12) {
5485 /* Check overflow and/or saturate */
5486 int l1 = gen_new_label();
5487
5488 if (opc3 & 0x10) {
5489 /* Start with XER OV disabled, the most likely case */
5490 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5491 }
5492 if (opc3 & 0x01) {
5493 /* Signed */
5494 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5495 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5496 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5497 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5498 if (opc3 & 0x02) {
182608d4
AJ
5499 /* Saturate */
5500 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5501 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5502 }
5503 } else {
5504 /* Unsigned */
5505 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5506 if (opc3 & 0x02) {
182608d4
AJ
5507 /* Saturate */
5508 tcg_gen_movi_tl(t0, UINT32_MAX);
5509 }
5510 }
5511 if (opc3 & 0x10) {
5512 /* Check overflow */
5513 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5514 }
5515 gen_set_label(l1);
5516 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5517 }
5518 } else {
5519 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5520 }
182608d4
AJ
5521 tcg_temp_free(t0);
5522 tcg_temp_free(t1);
76a66253
JM
5523 if (unlikely(Rc) != 0) {
5524 /* Update Rc0 */
182608d4 5525 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5526 }
5527}
5528
a750fc0b
JM
5529#define GEN_MAC_HANDLER(name, opc2, opc3) \
5530GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
76a66253
JM
5531{ \
5532 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5533 rD(ctx->opcode), Rc(ctx->opcode)); \
5534}
5535
5536/* macchw - macchw. */
a750fc0b 5537GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5538/* macchwo - macchwo. */
a750fc0b 5539GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5540/* macchws - macchws. */
a750fc0b 5541GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5542/* macchwso - macchwso. */
a750fc0b 5543GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5544/* macchwsu - macchwsu. */
a750fc0b 5545GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5546/* macchwsuo - macchwsuo. */
a750fc0b 5547GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5548/* macchwu - macchwu. */
a750fc0b 5549GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5550/* macchwuo - macchwuo. */
a750fc0b 5551GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5552/* machhw - machhw. */
a750fc0b 5553GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5554/* machhwo - machhwo. */
a750fc0b 5555GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5556/* machhws - machhws. */
a750fc0b 5557GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5558/* machhwso - machhwso. */
a750fc0b 5559GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5560/* machhwsu - machhwsu. */
a750fc0b 5561GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5562/* machhwsuo - machhwsuo. */
a750fc0b 5563GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5564/* machhwu - machhwu. */
a750fc0b 5565GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5566/* machhwuo - machhwuo. */
a750fc0b 5567GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5568/* maclhw - maclhw. */
a750fc0b 5569GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5570/* maclhwo - maclhwo. */
a750fc0b 5571GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5572/* maclhws - maclhws. */
a750fc0b 5573GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5574/* maclhwso - maclhwso. */
a750fc0b 5575GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5576/* maclhwu - maclhwu. */
a750fc0b 5577GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5578/* maclhwuo - maclhwuo. */
a750fc0b 5579GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5580/* maclhwsu - maclhwsu. */
a750fc0b 5581GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5582/* maclhwsuo - maclhwsuo. */
a750fc0b 5583GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5584/* nmacchw - nmacchw. */
a750fc0b 5585GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5586/* nmacchwo - nmacchwo. */
a750fc0b 5587GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5588/* nmacchws - nmacchws. */
a750fc0b 5589GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5590/* nmacchwso - nmacchwso. */
a750fc0b 5591GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5592/* nmachhw - nmachhw. */
a750fc0b 5593GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5594/* nmachhwo - nmachhwo. */
a750fc0b 5595GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5596/* nmachhws - nmachhws. */
a750fc0b 5597GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5598/* nmachhwso - nmachhwso. */
a750fc0b 5599GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5600/* nmaclhw - nmaclhw. */
a750fc0b 5601GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5602/* nmaclhwo - nmaclhwo. */
a750fc0b 5603GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5604/* nmaclhws - nmaclhws. */
a750fc0b 5605GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5606/* nmaclhwso - nmaclhwso. */
a750fc0b 5607GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5608
5609/* mulchw - mulchw. */
a750fc0b 5610GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5611/* mulchwu - mulchwu. */
a750fc0b 5612GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5613/* mulhhw - mulhhw. */
a750fc0b 5614GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5615/* mulhhwu - mulhhwu. */
a750fc0b 5616GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5617/* mullhw - mullhw. */
a750fc0b 5618GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5619/* mullhwu - mullhwu. */
a750fc0b 5620GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5621
5622/* mfdcr */
05332d70 5623GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
76a66253
JM
5624{
5625#if defined(CONFIG_USER_ONLY)
e1833e1f 5626 GEN_EXCP_PRIVREG(ctx);
76a66253 5627#else
06dca6a7 5628 TCGv dcrn;
76a66253 5629 if (unlikely(!ctx->supervisor)) {
e1833e1f 5630 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5631 return;
5632 }
06dca6a7
AJ
5633 /* NIP cannot be restored if the memory exception comes from an helper */
5634 gen_update_nip(ctx, ctx->nip - 4);
5635 dcrn = tcg_const_tl(SPR(ctx->opcode));
5636 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], dcrn);
5637 tcg_temp_free(dcrn);
76a66253
JM
5638#endif
5639}
5640
5641/* mtdcr */
05332d70 5642GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
76a66253
JM
5643{
5644#if defined(CONFIG_USER_ONLY)
e1833e1f 5645 GEN_EXCP_PRIVREG(ctx);
76a66253 5646#else
06dca6a7 5647 TCGv dcrn;
76a66253 5648 if (unlikely(!ctx->supervisor)) {
e1833e1f 5649 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5650 return;
5651 }
06dca6a7
AJ
5652 /* NIP cannot be restored if the memory exception comes from an helper */
5653 gen_update_nip(ctx, ctx->nip - 4);
5654 dcrn = tcg_const_tl(SPR(ctx->opcode));
5655 gen_helper_store_dcr(dcrn, cpu_gpr[rS(ctx->opcode)]);
5656 tcg_temp_free(dcrn);
a42bd6cc
JM
5657#endif
5658}
5659
5660/* mfdcrx */
2662a059 5661/* XXX: not implemented on 440 ? */
05332d70 5662GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5663{
5664#if defined(CONFIG_USER_ONLY)
e1833e1f 5665 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5666#else
5667 if (unlikely(!ctx->supervisor)) {
e1833e1f 5668 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5669 return;
5670 }
06dca6a7
AJ
5671 /* NIP cannot be restored if the memory exception comes from an helper */
5672 gen_update_nip(ctx, ctx->nip - 4);
5673 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5674 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5675#endif
5676}
5677
5678/* mtdcrx */
2662a059 5679/* XXX: not implemented on 440 ? */
05332d70 5680GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5681{
5682#if defined(CONFIG_USER_ONLY)
e1833e1f 5683 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5684#else
5685 if (unlikely(!ctx->supervisor)) {
e1833e1f 5686 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5687 return;
5688 }
06dca6a7
AJ
5689 /* NIP cannot be restored if the memory exception comes from an helper */
5690 gen_update_nip(ctx, ctx->nip - 4);
5691 gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
a750fc0b 5692 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5693#endif
5694}
5695
a750fc0b
JM
5696/* mfdcrux (PPC 460) : user-mode access to DCR */
5697GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5698{
06dca6a7
AJ
5699 /* NIP cannot be restored if the memory exception comes from an helper */
5700 gen_update_nip(ctx, ctx->nip - 4);
5701 gen_helper_load_dcr(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
a750fc0b
JM
5702 /* Note: Rc update flag set leads to undefined state of Rc0 */
5703}
5704
5705/* mtdcrux (PPC 460) : user-mode access to DCR */
5706GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5707{
06dca6a7
AJ
5708 /* NIP cannot be restored if the memory exception comes from an helper */
5709 gen_update_nip(ctx, ctx->nip - 4);
5710 gen_helper_store_dcr(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
5711 /* Note: Rc update flag set leads to undefined state of Rc0 */
5712}
5713
76a66253
JM
5714/* dccci */
5715GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5716{
5717#if defined(CONFIG_USER_ONLY)
e1833e1f 5718 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5719#else
5720 if (unlikely(!ctx->supervisor)) {
e1833e1f 5721 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5722 return;
5723 }
5724 /* interpreted as no-op */
5725#endif
5726}
5727
5728/* dcread */
5729GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5730{
5731#if defined(CONFIG_USER_ONLY)
e1833e1f 5732 GEN_EXCP_PRIVOPC(ctx);
76a66253 5733#else
b61f2753 5734 TCGv EA, val;
76a66253 5735 if (unlikely(!ctx->supervisor)) {
e1833e1f 5736 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5737 return;
5738 }
a7812ae4 5739 EA = tcg_temp_new();
a7859e89 5740 gen_set_access_type(ACCESS_CACHE);
b61f2753 5741 gen_addr_reg_index(EA, ctx);
a7812ae4 5742 val = tcg_temp_new();
b61f2753
AJ
5743 gen_qemu_ld32u(val, EA, ctx->mem_idx);
5744 tcg_temp_free(val);
5745 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5746 tcg_temp_free(EA);
76a66253
JM
5747#endif
5748}
5749
5750/* icbt */
c7697e1f 5751GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
76a66253
JM
5752{
5753 /* interpreted as no-op */
5754 /* XXX: specification say this is treated as a load by the MMU
5755 * but does not generate any exception
5756 */
5757}
5758
5759/* iccci */
5760GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5761{
5762#if defined(CONFIG_USER_ONLY)
e1833e1f 5763 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5764#else
5765 if (unlikely(!ctx->supervisor)) {
e1833e1f 5766 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5767 return;
5768 }
5769 /* interpreted as no-op */
5770#endif
5771}
5772
5773/* icread */
5774GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5775{
5776#if defined(CONFIG_USER_ONLY)
e1833e1f 5777 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5778#else
5779 if (unlikely(!ctx->supervisor)) {
e1833e1f 5780 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5781 return;
5782 }
5783 /* interpreted as no-op */
5784#endif
5785}
5786
5787/* rfci (supervisor only) */
c7697e1f 5788GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
a42bd6cc
JM
5789{
5790#if defined(CONFIG_USER_ONLY)
e1833e1f 5791 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5792#else
5793 if (unlikely(!ctx->supervisor)) {
e1833e1f 5794 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5795 return;
5796 }
5797 /* Restore CPU state */
d72a19f7 5798 gen_helper_40x_rfci();
e1833e1f 5799 GEN_SYNC(ctx);
a42bd6cc
JM
5800#endif
5801}
5802
5803GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5804{
5805#if defined(CONFIG_USER_ONLY)
e1833e1f 5806 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5807#else
5808 if (unlikely(!ctx->supervisor)) {
e1833e1f 5809 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5810 return;
5811 }
5812 /* Restore CPU state */
d72a19f7 5813 gen_helper_rfci();
e1833e1f 5814 GEN_SYNC(ctx);
a42bd6cc
JM
5815#endif
5816}
5817
5818/* BookE specific */
2662a059 5819/* XXX: not implemented on 440 ? */
05332d70 5820GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
76a66253
JM
5821{
5822#if defined(CONFIG_USER_ONLY)
e1833e1f 5823 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5824#else
5825 if (unlikely(!ctx->supervisor)) {
e1833e1f 5826 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5827 return;
5828 }
5829 /* Restore CPU state */
d72a19f7 5830 gen_helper_rfdi();
e1833e1f 5831 GEN_SYNC(ctx);
76a66253
JM
5832#endif
5833}
5834
2662a059 5835/* XXX: not implemented on 440 ? */
a750fc0b 5836GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
a42bd6cc
JM
5837{
5838#if defined(CONFIG_USER_ONLY)
e1833e1f 5839 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5840#else
5841 if (unlikely(!ctx->supervisor)) {
e1833e1f 5842 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5843 return;
5844 }
5845 /* Restore CPU state */
d72a19f7 5846 gen_helper_rfmci();
e1833e1f 5847 GEN_SYNC(ctx);
a42bd6cc
JM
5848#endif
5849}
5eb7995e 5850
d9bce9d9 5851/* TLB management - PowerPC 405 implementation */
76a66253 5852/* tlbre */
c7697e1f 5853GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
76a66253
JM
5854{
5855#if defined(CONFIG_USER_ONLY)
e1833e1f 5856 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5857#else
5858 if (unlikely(!ctx->supervisor)) {
e1833e1f 5859 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5860 return;
5861 }
5862 switch (rB(ctx->opcode)) {
5863 case 0:
f78fb44e 5864 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5865 gen_op_4xx_tlbre_hi();
f78fb44e 5866 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5867 break;
5868 case 1:
f78fb44e 5869 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5870 gen_op_4xx_tlbre_lo();
f78fb44e 5871 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5872 break;
5873 default:
e1833e1f 5874 GEN_EXCP_INVAL(ctx);
76a66253 5875 break;
9a64fbe4 5876 }
76a66253
JM
5877#endif
5878}
5879
d9bce9d9 5880/* tlbsx - tlbsx. */
c7697e1f 5881GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
76a66253
JM
5882{
5883#if defined(CONFIG_USER_ONLY)
e1833e1f 5884 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5885#else
5886 if (unlikely(!ctx->supervisor)) {
e1833e1f 5887 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5888 return;
5889 }
e2be8d8d 5890 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5891 gen_op_4xx_tlbsx();
76a66253 5892 if (Rc(ctx->opcode))
daf4f96e 5893 gen_op_4xx_tlbsx_check();
f78fb44e 5894 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 5895#endif
79aceca5
FB
5896}
5897
76a66253 5898/* tlbwe */
c7697e1f 5899GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
79aceca5 5900{
76a66253 5901#if defined(CONFIG_USER_ONLY)
e1833e1f 5902 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5903#else
5904 if (unlikely(!ctx->supervisor)) {
e1833e1f 5905 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5906 return;
5907 }
5908 switch (rB(ctx->opcode)) {
5909 case 0:
f78fb44e
AJ
5910 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5911 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5912 gen_op_4xx_tlbwe_hi();
5913 break;
5914 case 1:
f78fb44e
AJ
5915 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5916 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5917 gen_op_4xx_tlbwe_lo();
5918 break;
5919 default:
e1833e1f 5920 GEN_EXCP_INVAL(ctx);
76a66253 5921 break;
9a64fbe4 5922 }
76a66253
JM
5923#endif
5924}
5925
a4bb6c3e 5926/* TLB management - PowerPC 440 implementation */
5eb7995e 5927/* tlbre */
c7697e1f 5928GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5929{
5930#if defined(CONFIG_USER_ONLY)
e1833e1f 5931 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5932#else
5933 if (unlikely(!ctx->supervisor)) {
e1833e1f 5934 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5935 return;
5936 }
5937 switch (rB(ctx->opcode)) {
5938 case 0:
5eb7995e 5939 case 1:
5eb7995e 5940 case 2:
f78fb44e 5941 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a4bb6c3e 5942 gen_op_440_tlbre(rB(ctx->opcode));
f78fb44e 5943 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5944 break;
5945 default:
e1833e1f 5946 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5947 break;
5948 }
5949#endif
5950}
5951
5952/* tlbsx - tlbsx. */
c7697e1f 5953GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5eb7995e
JM
5954{
5955#if defined(CONFIG_USER_ONLY)
e1833e1f 5956 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5957#else
5958 if (unlikely(!ctx->supervisor)) {
e1833e1f 5959 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5960 return;
5961 }
e2be8d8d 5962 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5963 gen_op_440_tlbsx();
5eb7995e 5964 if (Rc(ctx->opcode))
daf4f96e 5965 gen_op_4xx_tlbsx_check();
f78fb44e 5966 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5967#endif
5968}
5969
5970/* tlbwe */
c7697e1f 5971GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5972{
5973#if defined(CONFIG_USER_ONLY)
e1833e1f 5974 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5975#else
5976 if (unlikely(!ctx->supervisor)) {
e1833e1f 5977 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5978 return;
5979 }
5980 switch (rB(ctx->opcode)) {
5981 case 0:
5eb7995e 5982 case 1:
5eb7995e 5983 case 2:
f78fb44e
AJ
5984 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5985 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a4bb6c3e 5986 gen_op_440_tlbwe(rB(ctx->opcode));
5eb7995e
JM
5987 break;
5988 default:
e1833e1f 5989 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5990 break;
5991 }
5992#endif
5993}
5994
76a66253 5995/* wrtee */
05332d70 5996GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
76a66253
JM
5997{
5998#if defined(CONFIG_USER_ONLY)
e1833e1f 5999 GEN_EXCP_PRIVOPC(ctx);
76a66253 6000#else
6527f6ea 6001 TCGv t0;
76a66253 6002 if (unlikely(!ctx->supervisor)) {
e1833e1f 6003 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
6004 return;
6005 }
6527f6ea
AJ
6006 t0 = tcg_temp_new();
6007 tcg_gen_andi_tl(t0, cpu_gpr[rD(ctx->opcode)], (1 << MSR_EE));
6008 tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
6009 tcg_gen_or_tl(cpu_msr, cpu_msr, t0);
6010 tcg_temp_free(t0);
dee96f6c
JM
6011 /* Stop translation to have a chance to raise an exception
6012 * if we just set msr_ee to 1
6013 */
e1833e1f 6014 GEN_STOP(ctx);
76a66253
JM
6015#endif
6016}
6017
6018/* wrteei */
05332d70 6019GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
76a66253
JM
6020{
6021#if defined(CONFIG_USER_ONLY)
e1833e1f 6022 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
6023#else
6024 if (unlikely(!ctx->supervisor)) {
e1833e1f 6025 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
6026 return;
6027 }
6527f6ea
AJ
6028 if (ctx->opcode & 0x00010000) {
6029 tcg_gen_ori_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6030 /* Stop translation to have a chance to raise an exception */
6031 GEN_STOP(ctx);
6032 } else {
6033 tcg_gen_andi_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
6034 }
76a66253
JM
6035#endif
6036}
6037
08e46e54 6038/* PowerPC 440 specific instructions */
76a66253
JM
6039/* dlmzb */
6040GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
6041{
ef0d51af
AJ
6042 TCGv_i32 t0 = tcg_const_i32(Rc(ctx->opcode));
6043 gen_helper_dlmzb(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rS(ctx->opcode)],
6044 cpu_gpr[rB(ctx->opcode)], t0);
6045 tcg_temp_free_i32(t0);
76a66253
JM
6046}
6047
6048/* mbar replaces eieio on 440 */
6049GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
6050{
6051 /* interpreted as no-op */
6052}
6053
6054/* msync replaces sync on 440 */
0db1b20e 6055GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
76a66253
JM
6056{
6057 /* interpreted as no-op */
6058}
6059
6060/* icbt */
c7697e1f 6061GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
76a66253
JM
6062{
6063 /* interpreted as no-op */
6064 /* XXX: specification say this is treated as a load by the MMU
6065 * but does not generate any exception
6066 */
79aceca5
FB
6067}
6068
a9d9eb8f
JM
6069/*** Altivec vector extension ***/
6070/* Altivec registers moves */
a9d9eb8f 6071
a9d9eb8f 6072#define GEN_VR_LDX(name, opc2, opc3) \
fe1e5c53 6073GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
a9d9eb8f 6074{ \
fe1e5c53 6075 TCGv EA; \
a9d9eb8f
JM
6076 if (unlikely(!ctx->altivec_enabled)) { \
6077 GEN_EXCP_NO_VR(ctx); \
6078 return; \
6079 } \
fe1e5c53
AJ
6080 EA = tcg_temp_new(); \
6081 gen_addr_reg_index(EA, ctx); \
6082 tcg_gen_andi_tl(EA, EA, ~0xf); \
6083 if (ctx->mem_idx & 1) { \
6084 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
6085 tcg_gen_addi_tl(EA, EA, 8); \
6086 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
6087 } else { \
6088 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
6089 tcg_gen_addi_tl(EA, EA, 8); \
6090 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
6091 } \
6092 tcg_temp_free(EA); \
a9d9eb8f
JM
6093}
6094
6095#define GEN_VR_STX(name, opc2, opc3) \
6096GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
6097{ \
fe1e5c53 6098 TCGv EA; \
a9d9eb8f
JM
6099 if (unlikely(!ctx->altivec_enabled)) { \
6100 GEN_EXCP_NO_VR(ctx); \
6101 return; \
6102 } \
fe1e5c53
AJ
6103 EA = tcg_temp_new(); \
6104 gen_addr_reg_index(EA, ctx); \
6105 tcg_gen_andi_tl(EA, EA, ~0xf); \
6106 if (ctx->mem_idx & 1) { \
6107 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
6108 tcg_gen_addi_tl(EA, EA, 8); \
6109 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
6110 } else { \
6111 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
6112 tcg_gen_addi_tl(EA, EA, 8); \
6113 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
6114 } \
6115 tcg_temp_free(EA); \
a9d9eb8f
JM
6116}
6117
fe1e5c53 6118GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 6119/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 6120GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 6121
fe1e5c53 6122GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 6123/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 6124GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 6125
0487d6a8 6126/*** SPE extension ***/
0487d6a8 6127/* Register moves */
3cd7d1dd 6128
a7812ae4 6129static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
f78fb44e
AJ
6130#if defined(TARGET_PPC64)
6131 tcg_gen_mov_i64(t, cpu_gpr[reg]);
6132#else
36aa55dc 6133 tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
3cd7d1dd 6134#endif
f78fb44e 6135}
3cd7d1dd 6136
a7812ae4 6137static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
f78fb44e
AJ
6138#if defined(TARGET_PPC64)
6139 tcg_gen_mov_i64(cpu_gpr[reg], t);
6140#else
a7812ae4 6141 TCGv_i64 tmp = tcg_temp_new_i64();
f78fb44e 6142 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
f78fb44e
AJ
6143 tcg_gen_shri_i64(tmp, t, 32);
6144 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
a7812ae4 6145 tcg_temp_free_i64(tmp);
3cd7d1dd 6146#endif
f78fb44e 6147}
3cd7d1dd 6148
0487d6a8
JM
6149#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
6150GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
6151{ \
6152 if (Rc(ctx->opcode)) \
6153 gen_##name1(ctx); \
6154 else \
6155 gen_##name0(ctx); \
6156}
6157
6158/* Handler for undefined SPE opcodes */
b068d6a7 6159static always_inline void gen_speundef (DisasContext *ctx)
0487d6a8 6160{
e1833e1f 6161 GEN_EXCP_INVAL(ctx);
0487d6a8
JM
6162}
6163
57951c27
AJ
6164/* SPE logic */
6165#if defined(TARGET_PPC64)
6166#define GEN_SPEOP_LOGIC2(name, tcg_op) \
b068d6a7 6167static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6168{ \
6169 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6170 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6171 return; \
6172 } \
57951c27
AJ
6173 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6174 cpu_gpr[rB(ctx->opcode)]); \
6175}
6176#else
6177#define GEN_SPEOP_LOGIC2(name, tcg_op) \
6178static always_inline void gen_##name (DisasContext *ctx) \
6179{ \
6180 if (unlikely(!ctx->spe_enabled)) { \
6181 GEN_EXCP_NO_AP(ctx); \
6182 return; \
6183 } \
6184 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6185 cpu_gpr[rB(ctx->opcode)]); \
6186 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6187 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6188}
57951c27
AJ
6189#endif
6190
6191GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6192GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6193GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6194GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6195GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6196GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6197GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6198GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 6199
57951c27
AJ
6200/* SPE logic immediate */
6201#if defined(TARGET_PPC64)
6202#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
3d3a6a0a
AJ
6203static always_inline void gen_##name (DisasContext *ctx) \
6204{ \
6205 if (unlikely(!ctx->spe_enabled)) { \
6206 GEN_EXCP_NO_AP(ctx); \
6207 return; \
6208 } \
a7812ae4
PB
6209 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6210 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6211 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6212 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6213 tcg_opi(t0, t0, rB(ctx->opcode)); \
6214 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6215 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6216 tcg_temp_free_i64(t2); \
57951c27
AJ
6217 tcg_opi(t1, t1, rB(ctx->opcode)); \
6218 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6219 tcg_temp_free_i32(t0); \
6220 tcg_temp_free_i32(t1); \
3d3a6a0a 6221}
57951c27
AJ
6222#else
6223#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
b068d6a7 6224static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6225{ \
6226 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6227 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6228 return; \
6229 } \
57951c27
AJ
6230 tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6231 rB(ctx->opcode)); \
6232 tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6233 rB(ctx->opcode)); \
0487d6a8 6234}
57951c27
AJ
6235#endif
6236GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6237GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6238GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6239GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 6240
57951c27
AJ
6241/* SPE arithmetic */
6242#if defined(TARGET_PPC64)
6243#define GEN_SPEOP_ARITH1(name, tcg_op) \
b068d6a7 6244static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6245{ \
6246 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6247 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6248 return; \
6249 } \
a7812ae4
PB
6250 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6251 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6252 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6253 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6254 tcg_op(t0, t0); \
6255 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6256 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6257 tcg_temp_free_i64(t2); \
57951c27
AJ
6258 tcg_op(t1, t1); \
6259 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6260 tcg_temp_free_i32(t0); \
6261 tcg_temp_free_i32(t1); \
0487d6a8 6262}
57951c27 6263#else
a7812ae4 6264#define GEN_SPEOP_ARITH1(name, tcg_op) \
57951c27
AJ
6265static always_inline void gen_##name (DisasContext *ctx) \
6266{ \
6267 if (unlikely(!ctx->spe_enabled)) { \
6268 GEN_EXCP_NO_AP(ctx); \
6269 return; \
6270 } \
6271 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6272 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
6273}
6274#endif
0487d6a8 6275
a7812ae4 6276static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
57951c27
AJ
6277{
6278 int l1 = gen_new_label();
6279 int l2 = gen_new_label();
0487d6a8 6280
57951c27
AJ
6281 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6282 tcg_gen_neg_i32(ret, arg1);
6283 tcg_gen_br(l2);
6284 gen_set_label(l1);
a7812ae4 6285 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
6286 gen_set_label(l2);
6287}
6288GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6289GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6290GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6291GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
a7812ae4 6292static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 6293{
57951c27
AJ
6294 tcg_gen_addi_i32(ret, arg1, 0x8000);
6295 tcg_gen_ext16u_i32(ret, ret);
6296}
6297GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
6298GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6299GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 6300
57951c27
AJ
6301#if defined(TARGET_PPC64)
6302#define GEN_SPEOP_ARITH2(name, tcg_op) \
6303static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6304{ \
6305 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6306 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6307 return; \
6308 } \
a7812ae4
PB
6309 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6310 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6311 TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6312 TCGv_i64 t3 = tcg_temp_local_new(TCG_TYPE_I64); \
57951c27
AJ
6313 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6314 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6315 tcg_op(t0, t0, t2); \
6316 tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6317 tcg_gen_trunc_i64_i32(t1, t3); \
6318 tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6319 tcg_gen_trunc_i64_i32(t2, t3); \
a7812ae4 6320 tcg_temp_free_i64(t3); \
57951c27 6321 tcg_op(t1, t1, t2); \
a7812ae4 6322 tcg_temp_free_i32(t2); \
57951c27 6323 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6324 tcg_temp_free_i32(t0); \
6325 tcg_temp_free_i32(t1); \
0487d6a8 6326}
57951c27
AJ
6327#else
6328#define GEN_SPEOP_ARITH2(name, tcg_op) \
6329static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6330{ \
6331 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6332 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6333 return; \
6334 } \
57951c27
AJ
6335 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6336 cpu_gpr[rB(ctx->opcode)]); \
6337 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6338 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6339}
57951c27 6340#endif
0487d6a8 6341
a7812ae4 6342static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6343{
a7812ae4 6344 TCGv_i32 t0;
57951c27 6345 int l1, l2;
0487d6a8 6346
57951c27
AJ
6347 l1 = gen_new_label();
6348 l2 = gen_new_label();
a7812ae4 6349 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6350 /* No error here: 6 bits are used */
6351 tcg_gen_andi_i32(t0, arg2, 0x3F);
6352 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6353 tcg_gen_shr_i32(ret, arg1, t0);
6354 tcg_gen_br(l2);
6355 gen_set_label(l1);
6356 tcg_gen_movi_i32(ret, 0);
6357 tcg_gen_br(l2);
a7812ae4 6358 tcg_temp_free_i32(t0);
57951c27
AJ
6359}
6360GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
a7812ae4 6361static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6362{
a7812ae4 6363 TCGv_i32 t0;
57951c27
AJ
6364 int l1, l2;
6365
6366 l1 = gen_new_label();
6367 l2 = gen_new_label();
a7812ae4 6368 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6369 /* No error here: 6 bits are used */
6370 tcg_gen_andi_i32(t0, arg2, 0x3F);
6371 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6372 tcg_gen_sar_i32(ret, arg1, t0);
6373 tcg_gen_br(l2);
6374 gen_set_label(l1);
6375 tcg_gen_movi_i32(ret, 0);
6376 tcg_gen_br(l2);
a7812ae4 6377 tcg_temp_free_i32(t0);
57951c27
AJ
6378}
6379GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
a7812ae4 6380static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6381{
a7812ae4 6382 TCGv_i32 t0;
57951c27
AJ
6383 int l1, l2;
6384
6385 l1 = gen_new_label();
6386 l2 = gen_new_label();
a7812ae4 6387 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6388 /* No error here: 6 bits are used */
6389 tcg_gen_andi_i32(t0, arg2, 0x3F);
6390 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6391 tcg_gen_shl_i32(ret, arg1, t0);
6392 tcg_gen_br(l2);
6393 gen_set_label(l1);
6394 tcg_gen_movi_i32(ret, 0);
6395 tcg_gen_br(l2);
a7812ae4 6396 tcg_temp_free_i32(t0);
57951c27
AJ
6397}
6398GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
a7812ae4 6399static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6400{
a7812ae4 6401 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
6402 tcg_gen_andi_i32(t0, arg2, 0x1F);
6403 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 6404 tcg_temp_free_i32(t0);
57951c27
AJ
6405}
6406GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6407static always_inline void gen_evmergehi (DisasContext *ctx)
6408{
6409 if (unlikely(!ctx->spe_enabled)) {
6410 GEN_EXCP_NO_AP(ctx);
6411 return;
6412 }
6413#if defined(TARGET_PPC64)
a7812ae4
PB
6414 TCGv t0 = tcg_temp_new();
6415 TCGv t1 = tcg_temp_new();
57951c27
AJ
6416 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6417 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6418 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6419 tcg_temp_free(t0);
6420 tcg_temp_free(t1);
6421#else
6422 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6423 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6424#endif
6425}
6426GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
a7812ae4 6427static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 6428{
57951c27
AJ
6429 tcg_gen_sub_i32(ret, arg2, arg1);
6430}
6431GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 6432
57951c27
AJ
6433/* SPE arithmetic immediate */
6434#if defined(TARGET_PPC64)
6435#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6436static always_inline void gen_##name (DisasContext *ctx) \
6437{ \
6438 if (unlikely(!ctx->spe_enabled)) { \
6439 GEN_EXCP_NO_AP(ctx); \
6440 return; \
6441 } \
a7812ae4
PB
6442 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6443 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6444 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6445 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6446 tcg_op(t0, t0, rA(ctx->opcode)); \
6447 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6448 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6449 tcg_temp_free_i64(t2); \
57951c27
AJ
6450 tcg_op(t1, t1, rA(ctx->opcode)); \
6451 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6452 tcg_temp_free_i32(t0); \
6453 tcg_temp_free_i32(t1); \
57951c27
AJ
6454}
6455#else
6456#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6457static always_inline void gen_##name (DisasContext *ctx) \
6458{ \
6459 if (unlikely(!ctx->spe_enabled)) { \
6460 GEN_EXCP_NO_AP(ctx); \
6461 return; \
6462 } \
6463 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
6464 rA(ctx->opcode)); \
6465 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
6466 rA(ctx->opcode)); \
6467}
6468#endif
6469GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6470GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6471
6472/* SPE comparison */
6473#if defined(TARGET_PPC64)
6474#define GEN_SPEOP_COMP(name, tcg_cond) \
6475static always_inline void gen_##name (DisasContext *ctx) \
6476{ \
6477 if (unlikely(!ctx->spe_enabled)) { \
6478 GEN_EXCP_NO_AP(ctx); \
6479 return; \
6480 } \
6481 int l1 = gen_new_label(); \
6482 int l2 = gen_new_label(); \
6483 int l3 = gen_new_label(); \
6484 int l4 = gen_new_label(); \
a7812ae4
PB
6485 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6486 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6487 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6488 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6489 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
6490 tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
a7812ae4 6491 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
6492 tcg_gen_br(l2); \
6493 gen_set_label(l1); \
6494 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6495 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6496 gen_set_label(l2); \
6497 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6498 tcg_gen_trunc_i64_i32(t0, t2); \
6499 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6500 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6501 tcg_temp_free_i64(t2); \
57951c27
AJ
6502 tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
6503 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6504 ~(CRF_CH | CRF_CH_AND_CL)); \
6505 tcg_gen_br(l4); \
6506 gen_set_label(l3); \
6507 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6508 CRF_CH | CRF_CH_OR_CL); \
6509 gen_set_label(l4); \
a7812ae4
PB
6510 tcg_temp_free_i32(t0); \
6511 tcg_temp_free_i32(t1); \
57951c27
AJ
6512}
6513#else
6514#define GEN_SPEOP_COMP(name, tcg_cond) \
6515static always_inline void gen_##name (DisasContext *ctx) \
6516{ \
6517 if (unlikely(!ctx->spe_enabled)) { \
6518 GEN_EXCP_NO_AP(ctx); \
6519 return; \
6520 } \
6521 int l1 = gen_new_label(); \
6522 int l2 = gen_new_label(); \
6523 int l3 = gen_new_label(); \
6524 int l4 = gen_new_label(); \
6525 \
6526 tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
6527 cpu_gpr[rB(ctx->opcode)], l1); \
6528 tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
6529 tcg_gen_br(l2); \
6530 gen_set_label(l1); \
6531 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6532 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6533 gen_set_label(l2); \
6534 tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
6535 cpu_gprh[rB(ctx->opcode)], l3); \
6536 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6537 ~(CRF_CH | CRF_CH_AND_CL)); \
6538 tcg_gen_br(l4); \
6539 gen_set_label(l3); \
6540 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6541 CRF_CH | CRF_CH_OR_CL); \
6542 gen_set_label(l4); \
6543}
6544#endif
6545GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6546GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6547GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6548GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6549GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6550
6551/* SPE misc */
6552static always_inline void gen_brinc (DisasContext *ctx)
6553{
6554 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
6555 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6556 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 6557}
57951c27
AJ
6558static always_inline void gen_evmergelo (DisasContext *ctx)
6559{
6560 if (unlikely(!ctx->spe_enabled)) {
6561 GEN_EXCP_NO_AP(ctx);
6562 return;
6563 }
6564#if defined(TARGET_PPC64)
a7812ae4
PB
6565 TCGv t0 = tcg_temp_new();
6566 TCGv t1 = tcg_temp_new();
57951c27
AJ
6567 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6568 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6569 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6570 tcg_temp_free(t0);
6571 tcg_temp_free(t1);
6572#else
6573 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6574 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6575#endif
6576}
6577static always_inline void gen_evmergehilo (DisasContext *ctx)
6578{
6579 if (unlikely(!ctx->spe_enabled)) {
6580 GEN_EXCP_NO_AP(ctx);
6581 return;
6582 }
6583#if defined(TARGET_PPC64)
a7812ae4
PB
6584 TCGv t0 = tcg_temp_new();
6585 TCGv t1 = tcg_temp_new();
57951c27
AJ
6586 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6587 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6588 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6589 tcg_temp_free(t0);
6590 tcg_temp_free(t1);
6591#else
6592 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6593 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6594#endif
6595}
6596static always_inline void gen_evmergelohi (DisasContext *ctx)
6597{
6598 if (unlikely(!ctx->spe_enabled)) {
6599 GEN_EXCP_NO_AP(ctx);
6600 return;
6601 }
6602#if defined(TARGET_PPC64)
a7812ae4
PB
6603 TCGv t0 = tcg_temp_new();
6604 TCGv t1 = tcg_temp_new();
57951c27
AJ
6605 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6606 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6607 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6608 tcg_temp_free(t0);
6609 tcg_temp_free(t1);
6610#else
6611 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6612 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6613#endif
6614}
6615static always_inline void gen_evsplati (DisasContext *ctx)
6616{
38d14952 6617 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
0487d6a8 6618
57951c27 6619#if defined(TARGET_PPC64)
38d14952 6620 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6621#else
6622 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6623 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6624#endif
6625}
b068d6a7 6626static always_inline void gen_evsplatfi (DisasContext *ctx)
0487d6a8 6627{
38d14952 6628 uint64_t imm = rA(ctx->opcode) << 11;
0487d6a8 6629
57951c27 6630#if defined(TARGET_PPC64)
38d14952 6631 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6632#else
6633 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6634 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6635#endif
0487d6a8
JM
6636}
6637
57951c27
AJ
6638static always_inline void gen_evsel (DisasContext *ctx)
6639{
6640 int l1 = gen_new_label();
6641 int l2 = gen_new_label();
6642 int l3 = gen_new_label();
6643 int l4 = gen_new_label();
a7812ae4 6644 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 6645#if defined(TARGET_PPC64)
a7812ae4
PB
6646 TCGv t1 = tcg_temp_local_new();
6647 TCGv t2 = tcg_temp_local_new();
57951c27
AJ
6648#endif
6649 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
6650 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
6651#if defined(TARGET_PPC64)
6652 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6653#else
6654 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6655#endif
6656 tcg_gen_br(l2);
6657 gen_set_label(l1);
6658#if defined(TARGET_PPC64)
6659 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6660#else
6661 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6662#endif
6663 gen_set_label(l2);
6664 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
6665 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
6666#if defined(TARGET_PPC64)
6667 tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
6668#else
6669 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6670#endif
6671 tcg_gen_br(l4);
6672 gen_set_label(l3);
6673#if defined(TARGET_PPC64)
6674 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
6675#else
6676 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6677#endif
6678 gen_set_label(l4);
a7812ae4 6679 tcg_temp_free_i32(t0);
57951c27
AJ
6680#if defined(TARGET_PPC64)
6681 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
6682 tcg_temp_free(t1);
6683 tcg_temp_free(t2);
6684#endif
6685}
6686GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6687{
6688 gen_evsel(ctx);
6689}
6690GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6691{
6692 gen_evsel(ctx);
6693}
6694GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6695{
6696 gen_evsel(ctx);
6697}
6698GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6699{
6700 gen_evsel(ctx);
6701}
0487d6a8
JM
6702
6703GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6704GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
6705GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
6706GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
6707GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
6708GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
6709GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
6710GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
6711GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
6712GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
6713GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
6714GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
6715GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
6716GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
6717GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
6718GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
6719GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
6720GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
6721GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
6722GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
6723GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
6724GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
6725GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6726GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6727GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6728
6a6ae23f
AJ
6729/* SPE load and stores */
6730static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
6731{
6732 target_ulong uimm = rB(ctx->opcode);
6733
6734 if (rA(ctx->opcode) == 0)
6735 tcg_gen_movi_tl(EA, uimm << sh);
6736 else
6737 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
0487d6a8 6738}
6a6ae23f
AJ
6739
6740static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6741{
6742#if defined(TARGET_PPC64)
6743 gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6744#else
6745 TCGv_i64 t0 = tcg_temp_new_i64();
6746 gen_qemu_ld64(t0, addr, ctx->mem_idx);
6747 tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
6748 tcg_gen_shri_i64(t0, t0, 32);
6749 tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
6750 tcg_temp_free_i64(t0);
6751#endif
0487d6a8 6752}
6a6ae23f
AJ
6753
6754static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6755{
0487d6a8 6756#if defined(TARGET_PPC64)
6a6ae23f
AJ
6757 TCGv t0 = tcg_temp_new();
6758 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6759 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6760 tcg_gen_addi_tl(addr, addr, 4);
6761 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6762 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6763 tcg_temp_free(t0);
6764#else
6765 gen_qemu_ld32u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6766 tcg_gen_addi_tl(addr, addr, 4);
6767 gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6768#endif
0487d6a8 6769}
6a6ae23f
AJ
6770
6771static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6772{
6773 TCGv t0 = tcg_temp_new();
6774#if defined(TARGET_PPC64)
6775 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6776 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6777 tcg_gen_addi_tl(addr, addr, 2);
6778 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6779 tcg_gen_shli_tl(t0, t0, 32);
6780 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6781 tcg_gen_addi_tl(addr, addr, 2);
6782 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6783 tcg_gen_shli_tl(t0, t0, 16);
6784 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6785 tcg_gen_addi_tl(addr, addr, 2);
6786 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6787 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6788#else
6a6ae23f
AJ
6789 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6790 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6791 tcg_gen_addi_tl(addr, addr, 2);
6792 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6793 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6794 tcg_gen_addi_tl(addr, addr, 2);
6795 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6796 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6797 tcg_gen_addi_tl(addr, addr, 2);
6798 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6799 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6800#endif
6a6ae23f 6801 tcg_temp_free(t0);
0487d6a8
JM
6802}
6803
6a6ae23f
AJ
6804static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6805{
6806 TCGv t0 = tcg_temp_new();
6807 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6808#if defined(TARGET_PPC64)
6809 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6810 tcg_gen_shli_tl(t0, t0, 16);
6811 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6812#else
6813 tcg_gen_shli_tl(t0, t0, 16);
6814 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6815 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6816#endif
6817 tcg_temp_free(t0);
0487d6a8
JM
6818}
6819
6a6ae23f
AJ
6820static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6821{
6822 TCGv t0 = tcg_temp_new();
6823 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6824#if defined(TARGET_PPC64)
6825 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6826 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6827#else
6828 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6829 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6830#endif
6831 tcg_temp_free(t0);
0487d6a8
JM
6832}
6833
6a6ae23f
AJ
6834static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6835{
6836 TCGv t0 = tcg_temp_new();
6837 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6838#if defined(TARGET_PPC64)
6839 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6840 tcg_gen_ext32u_tl(t0, t0);
6841 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6842#else
6843 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6844 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6845#endif
6846 tcg_temp_free(t0);
6847}
6848
6849static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6850{
6851 TCGv t0 = tcg_temp_new();
6852#if defined(TARGET_PPC64)
6853 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6854 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6855 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6856 tcg_gen_shli_tl(t0, t0, 16);
6857 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6858#else
6859 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6860 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6861 tcg_gen_addi_tl(addr, addr, 2);
6862 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6863 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6864#endif
6865 tcg_temp_free(t0);
6866}
6867
6868static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6869{
6870#if defined(TARGET_PPC64)
6871 TCGv t0 = tcg_temp_new();
6872 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6873 tcg_gen_addi_tl(addr, addr, 2);
6874 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6875 tcg_gen_shli_tl(t0, t0, 32);
6876 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6877 tcg_temp_free(t0);
6878#else
6879 gen_qemu_ld16u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6880 tcg_gen_addi_tl(addr, addr, 2);
6881 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6882#endif
6883}
6884
6885static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6886{
6887#if defined(TARGET_PPC64)
6888 TCGv t0 = tcg_temp_new();
6889 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6890 tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
6891 tcg_gen_addi_tl(addr, addr, 2);
6892 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6893 tcg_gen_shli_tl(t0, t0, 32);
6894 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6895 tcg_temp_free(t0);
6896#else
6897 gen_qemu_ld16s(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6898 tcg_gen_addi_tl(addr, addr, 2);
6899 gen_qemu_ld16s(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6900#endif
6901}
6902
6903static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6904{
6905 TCGv t0 = tcg_temp_new();
6906 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
0487d6a8 6907#if defined(TARGET_PPC64)
6a6ae23f
AJ
6908 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6909 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6910#else
6911 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6912 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6913#endif
6914 tcg_temp_free(t0);
6915}
6916
6917static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6918{
6919 TCGv t0 = tcg_temp_new();
6920#if defined(TARGET_PPC64)
6921 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6922 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6923 tcg_gen_shli_tl(t0, t0, 32);
6924 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6925 tcg_gen_addi_tl(addr, addr, 2);
6926 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6927 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6928 tcg_gen_shli_tl(t0, t0, 16);
6929 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6930#else
6931 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6932 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6933 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6934 tcg_gen_addi_tl(addr, addr, 2);
6935 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6936 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6937 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
0487d6a8 6938#endif
6a6ae23f
AJ
6939 tcg_temp_free(t0);
6940}
6941
6942static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6943{
6944#if defined(TARGET_PPC64)
6945 gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
0487d6a8 6946#else
6a6ae23f
AJ
6947 TCGv_i64 t0 = tcg_temp_new_i64();
6948 tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
6949 gen_qemu_st64(t0, addr, ctx->mem_idx);
6950 tcg_temp_free_i64(t0);
6951#endif
6952}
6953
6954static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6955{
0487d6a8 6956#if defined(TARGET_PPC64)
6a6ae23f
AJ
6957 TCGv t0 = tcg_temp_new();
6958 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6959 gen_qemu_st32(t0, addr, ctx->mem_idx);
6960 tcg_temp_free(t0);
6961#else
6962 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6963#endif
6964 tcg_gen_addi_tl(addr, addr, 4);
6965 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6966}
6967
6968static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6969{
6970 TCGv t0 = tcg_temp_new();
6971#if defined(TARGET_PPC64)
6972 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6973#else
6974 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6975#endif
6976 gen_qemu_st16(t0, addr, ctx->mem_idx);
6977 tcg_gen_addi_tl(addr, addr, 2);
6978#if defined(TARGET_PPC64)
6979 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6980 gen_qemu_st16(t0, addr, ctx->mem_idx);
6981#else
6982 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6983#endif
6984 tcg_gen_addi_tl(addr, addr, 2);
6985 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6986 gen_qemu_st16(t0, addr, ctx->mem_idx);
6987 tcg_temp_free(t0);
6988 tcg_gen_addi_tl(addr, addr, 2);
6989 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6990}
6991
6992static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6993{
6994 TCGv t0 = tcg_temp_new();
6995#if defined(TARGET_PPC64)
6996 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6997#else
6998 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6999#endif
7000 gen_qemu_st16(t0, addr, ctx->mem_idx);
7001 tcg_gen_addi_tl(addr, addr, 2);
7002 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
7003 gen_qemu_st16(t0, addr, ctx->mem_idx);
7004 tcg_temp_free(t0);
7005}
7006
7007static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
7008{
7009#if defined(TARGET_PPC64)
7010 TCGv t0 = tcg_temp_new();
7011 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7012 gen_qemu_st16(t0, addr, ctx->mem_idx);
7013 tcg_temp_free(t0);
7014#else
7015 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
7016#endif
7017 tcg_gen_addi_tl(addr, addr, 2);
7018 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
7019}
7020
7021static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
7022{
7023#if defined(TARGET_PPC64)
7024 TCGv t0 = tcg_temp_new();
7025 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
7026 gen_qemu_st32(t0, addr, ctx->mem_idx);
7027 tcg_temp_free(t0);
7028#else
7029 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
7030#endif
7031}
7032
7033static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
7034{
7035 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
7036}
7037
7038#define GEN_SPEOP_LDST(name, opc2, sh) \
7039GEN_HANDLER(gen_##name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \
7040{ \
7041 TCGv t0; \
7042 if (unlikely(!ctx->spe_enabled)) { \
7043 GEN_EXCP_NO_AP(ctx); \
7044 return; \
7045 } \
7046 t0 = tcg_temp_new(); \
7047 if (Rc(ctx->opcode)) { \
7048 gen_addr_spe_imm_index(t0, ctx, sh); \
7049 } else { \
7050 gen_addr_reg_index(t0, ctx); \
7051 } \
7052 gen_op_##name(ctx, t0); \
7053 tcg_temp_free(t0); \
7054}
7055
7056GEN_SPEOP_LDST(evldd, 0x00, 3);
7057GEN_SPEOP_LDST(evldw, 0x01, 3);
7058GEN_SPEOP_LDST(evldh, 0x02, 3);
7059GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
7060GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
7061GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
7062GEN_SPEOP_LDST(evlwhe, 0x08, 2);
7063GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
7064GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
7065GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
7066GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
7067
7068GEN_SPEOP_LDST(evstdd, 0x10, 3);
7069GEN_SPEOP_LDST(evstdw, 0x11, 3);
7070GEN_SPEOP_LDST(evstdh, 0x12, 3);
7071GEN_SPEOP_LDST(evstwhe, 0x18, 2);
7072GEN_SPEOP_LDST(evstwho, 0x1A, 2);
7073GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
7074GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
7075
7076/* Multiply and add - TODO */
7077#if 0
7078GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
7079GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
7080GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
7081GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
7082GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
7083GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
7084GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
7085GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
7086GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
7087GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
7088GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
7089GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
7090
7091GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
7092GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
7093GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
7094GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
7095GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
7096GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
7097GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
7098GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
7099GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
7100GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
7101GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
7102GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
7103GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
7104GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
7105
7106GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
7107GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
7108GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
7109GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
7110GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
7111GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
7112
7113GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
7114GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
7115GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
7116GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
7117GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
7118GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
7119GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
7120GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
7121GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
7122GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
7123GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
7124GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
7125
7126GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
7127GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
7128GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
7129GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
7130GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
7131
7132GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
7133GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
7134GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
7135GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
7136GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
7137GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
7138GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
7139GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
7140GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
7141GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
7142GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
7143GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
7144
7145GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
7146GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
7147GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
7148GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
7149GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
7150#endif
7151
7152/*** SPE floating-point extension ***/
1c97856d
AJ
7153#if defined(TARGET_PPC64)
7154#define GEN_SPEFPUOP_CONV_32_32(name) \
b068d6a7 7155static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8 7156{ \
1c97856d
AJ
7157 TCGv_i32 t0; \
7158 TCGv t1; \
7159 t0 = tcg_temp_new_i32(); \
7160 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7161 gen_helper_##name(t0, t0); \
7162 t1 = tcg_temp_new(); \
7163 tcg_gen_extu_i32_tl(t1, t0); \
7164 tcg_temp_free_i32(t0); \
7165 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7166 0xFFFFFFFF00000000ULL); \
7167 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7168 tcg_temp_free(t1); \
0487d6a8 7169}
1c97856d
AJ
7170#define GEN_SPEFPUOP_CONV_32_64(name) \
7171static always_inline void gen_##name (DisasContext *ctx) \
7172{ \
7173 TCGv_i32 t0; \
7174 TCGv t1; \
7175 t0 = tcg_temp_new_i32(); \
7176 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7177 t1 = tcg_temp_new(); \
7178 tcg_gen_extu_i32_tl(t1, t0); \
7179 tcg_temp_free_i32(t0); \
7180 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7181 0xFFFFFFFF00000000ULL); \
7182 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7183 tcg_temp_free(t1); \
7184}
7185#define GEN_SPEFPUOP_CONV_64_32(name) \
7186static always_inline void gen_##name (DisasContext *ctx) \
7187{ \
7188 TCGv_i32 t0 = tcg_temp_new_i32(); \
7189 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7190 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7191 tcg_temp_free_i32(t0); \
7192}
7193#define GEN_SPEFPUOP_CONV_64_64(name) \
7194static always_inline void gen_##name (DisasContext *ctx) \
7195{ \
7196 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7197}
7198#define GEN_SPEFPUOP_ARITH2_32_32(name) \
57951c27
AJ
7199static always_inline void gen_##name (DisasContext *ctx) \
7200{ \
1c97856d
AJ
7201 TCGv_i32 t0, t1; \
7202 TCGv_i64 t2; \
57951c27
AJ
7203 if (unlikely(!ctx->spe_enabled)) { \
7204 GEN_EXCP_NO_AP(ctx); \
7205 return; \
7206 } \
1c97856d
AJ
7207 t0 = tcg_temp_new_i32(); \
7208 t1 = tcg_temp_new_i32(); \
7209 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7210 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7211 gen_helper_##name(t0, t0, t1); \
7212 tcg_temp_free_i32(t1); \
7213 t2 = tcg_temp_new(); \
7214 tcg_gen_extu_i32_tl(t2, t0); \
7215 tcg_temp_free_i32(t0); \
7216 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7217 0xFFFFFFFF00000000ULL); \
7218 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7219 tcg_temp_free(t2); \
57951c27 7220}
1c97856d 7221#define GEN_SPEFPUOP_ARITH2_64_64(name) \
57951c27
AJ
7222static always_inline void gen_##name (DisasContext *ctx) \
7223{ \
7224 if (unlikely(!ctx->spe_enabled)) { \
7225 GEN_EXCP_NO_AP(ctx); \
7226 return; \
7227 } \
1c97856d
AJ
7228 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7229 cpu_gpr[rB(ctx->opcode)]); \
57951c27 7230}
1c97856d 7231#define GEN_SPEFPUOP_COMP_32(name) \
57951c27
AJ
7232static always_inline void gen_##name (DisasContext *ctx) \
7233{ \
1c97856d 7234 TCGv_i32 t0, t1; \
57951c27
AJ
7235 if (unlikely(!ctx->spe_enabled)) { \
7236 GEN_EXCP_NO_AP(ctx); \
7237 return; \
7238 } \
1c97856d
AJ
7239 t0 = tcg_temp_new_i32(); \
7240 t1 = tcg_temp_new_i32(); \
7241 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7242 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7243 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7244 tcg_temp_free_i32(t0); \
7245 tcg_temp_free_i32(t1); \
7246}
7247#define GEN_SPEFPUOP_COMP_64(name) \
7248static always_inline void gen_##name (DisasContext *ctx) \
7249{ \
7250 if (unlikely(!ctx->spe_enabled)) { \
7251 GEN_EXCP_NO_AP(ctx); \
7252 return; \
7253 } \
7254 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7255 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7256}
7257#else
7258#define GEN_SPEFPUOP_CONV_32_32(name) \
7259static always_inline void gen_##name (DisasContext *ctx) \
7260{ \
7261 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
57951c27 7262}
1c97856d
AJ
7263#define GEN_SPEFPUOP_CONV_32_64(name) \
7264static always_inline void gen_##name (DisasContext *ctx) \
7265{ \
7266 TCGv_i64 t0 = tcg_temp_new_i64(); \
7267 gen_load_gpr64(t0, rB(ctx->opcode)); \
7268 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7269 tcg_temp_free_i64(t0); \
7270}
7271#define GEN_SPEFPUOP_CONV_64_32(name) \
7272static always_inline void gen_##name (DisasContext *ctx) \
7273{ \
7274 TCGv_i64 t0 = tcg_temp_new_i64(); \
7275 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7276 gen_store_gpr64(rD(ctx->opcode), t0); \
7277 tcg_temp_free_i64(t0); \
7278}
7279#define GEN_SPEFPUOP_CONV_64_64(name) \
7280static always_inline void gen_##name (DisasContext *ctx) \
7281{ \
7282 TCGv_i64 t0 = tcg_temp_new_i64(); \
7283 gen_load_gpr64(t0, rB(ctx->opcode)); \
7284 gen_helper_##name(t0, t0); \
7285 gen_store_gpr64(rD(ctx->opcode), t0); \
7286 tcg_temp_free_i64(t0); \
7287}
7288#define GEN_SPEFPUOP_ARITH2_32_32(name) \
7289static always_inline void gen_##name (DisasContext *ctx) \
7290{ \
7291 if (unlikely(!ctx->spe_enabled)) { \
7292 GEN_EXCP_NO_AP(ctx); \
7293 return; \
7294 } \
7295 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
7296 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7297}
7298#define GEN_SPEFPUOP_ARITH2_64_64(name) \
7299static always_inline void gen_##name (DisasContext *ctx) \
7300{ \
7301 TCGv_i64 t0, t1; \
7302 if (unlikely(!ctx->spe_enabled)) { \
7303 GEN_EXCP_NO_AP(ctx); \
7304 return; \
7305 } \
7306 t0 = tcg_temp_new_i64(); \
7307 t1 = tcg_temp_new_i64(); \
7308 gen_load_gpr64(t0, rA(ctx->opcode)); \
7309 gen_load_gpr64(t1, rB(ctx->opcode)); \
7310 gen_helper_##name(t0, t0, t1); \
7311 gen_store_gpr64(rD(ctx->opcode), t0); \
7312 tcg_temp_free_i64(t0); \
7313 tcg_temp_free_i64(t1); \
7314}
7315#define GEN_SPEFPUOP_COMP_32(name) \
7316static always_inline void gen_##name (DisasContext *ctx) \
7317{ \
7318 if (unlikely(!ctx->spe_enabled)) { \
7319 GEN_EXCP_NO_AP(ctx); \
7320 return; \
7321 } \
7322 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7323 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7324}
7325#define GEN_SPEFPUOP_COMP_64(name) \
7326static always_inline void gen_##name (DisasContext *ctx) \
7327{ \
7328 TCGv_i64 t0, t1; \
7329 if (unlikely(!ctx->spe_enabled)) { \
7330 GEN_EXCP_NO_AP(ctx); \
7331 return; \
7332 } \
7333 t0 = tcg_temp_new_i64(); \
7334 t1 = tcg_temp_new_i64(); \
7335 gen_load_gpr64(t0, rA(ctx->opcode)); \
7336 gen_load_gpr64(t1, rB(ctx->opcode)); \
7337 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7338 tcg_temp_free_i64(t0); \
7339 tcg_temp_free_i64(t1); \
7340}
7341#endif
57951c27 7342
0487d6a8
JM
7343/* Single precision floating-point vectors operations */
7344/* Arithmetic */
1c97856d
AJ
7345GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7346GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7347GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7348GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7349static always_inline void gen_evfsabs (DisasContext *ctx)
7350{
7351 if (unlikely(!ctx->spe_enabled)) {
7352 GEN_EXCP_NO_AP(ctx);
7353 return;
7354 }
7355#if defined(TARGET_PPC64)
7356 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7357#else
7358 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7359 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7360#endif
7361}
7362static always_inline void gen_evfsnabs (DisasContext *ctx)
7363{
7364 if (unlikely(!ctx->spe_enabled)) {
7365 GEN_EXCP_NO_AP(ctx);
7366 return;
7367 }
7368#if defined(TARGET_PPC64)
7369 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7370#else
7371 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7372 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7373#endif
7374}
7375static always_inline void gen_evfsneg (DisasContext *ctx)
7376{
7377 if (unlikely(!ctx->spe_enabled)) {
7378 GEN_EXCP_NO_AP(ctx);
7379 return;
7380 }
7381#if defined(TARGET_PPC64)
7382 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7383#else
7384 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7385 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7386#endif
7387}
7388
0487d6a8 7389/* Conversion */
1c97856d
AJ
7390GEN_SPEFPUOP_CONV_64_64(evfscfui);
7391GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7392GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7393GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7394GEN_SPEFPUOP_CONV_64_64(evfsctui);
7395GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7396GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7397GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7398GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7399GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7400
0487d6a8 7401/* Comparison */
1c97856d
AJ
7402GEN_SPEFPUOP_COMP_64(evfscmpgt);
7403GEN_SPEFPUOP_COMP_64(evfscmplt);
7404GEN_SPEFPUOP_COMP_64(evfscmpeq);
7405GEN_SPEFPUOP_COMP_64(evfststgt);
7406GEN_SPEFPUOP_COMP_64(evfststlt);
7407GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
7408
7409/* Opcodes definitions */
7410GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
7411GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
7412GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
7413GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
7414GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
7415GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
7416GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
7417GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
7418GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
7419GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
7420GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
7421GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
7422GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
7423GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
7424
7425/* Single precision floating-point operations */
7426/* Arithmetic */
1c97856d
AJ
7427GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7428GEN_SPEFPUOP_ARITH2_32_32(efssub);
7429GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7430GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7431static always_inline void gen_efsabs (DisasContext *ctx)
7432{
7433 if (unlikely(!ctx->spe_enabled)) {
7434 GEN_EXCP_NO_AP(ctx);
7435 return;
7436 }
7437 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7438}
7439static always_inline void gen_efsnabs (DisasContext *ctx)
7440{
7441 if (unlikely(!ctx->spe_enabled)) {
7442 GEN_EXCP_NO_AP(ctx);
7443 return;
7444 }
7445 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7446}
7447static always_inline void gen_efsneg (DisasContext *ctx)
7448{
7449 if (unlikely(!ctx->spe_enabled)) {
7450 GEN_EXCP_NO_AP(ctx);
7451 return;
7452 }
7453 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7454}
7455
0487d6a8 7456/* Conversion */
1c97856d
AJ
7457GEN_SPEFPUOP_CONV_32_32(efscfui);
7458GEN_SPEFPUOP_CONV_32_32(efscfsi);
7459GEN_SPEFPUOP_CONV_32_32(efscfuf);
7460GEN_SPEFPUOP_CONV_32_32(efscfsf);
7461GEN_SPEFPUOP_CONV_32_32(efsctui);
7462GEN_SPEFPUOP_CONV_32_32(efsctsi);
7463GEN_SPEFPUOP_CONV_32_32(efsctuf);
7464GEN_SPEFPUOP_CONV_32_32(efsctsf);
7465GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7466GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7467GEN_SPEFPUOP_CONV_32_64(efscfd);
7468
0487d6a8 7469/* Comparison */
1c97856d
AJ
7470GEN_SPEFPUOP_COMP_32(efscmpgt);
7471GEN_SPEFPUOP_COMP_32(efscmplt);
7472GEN_SPEFPUOP_COMP_32(efscmpeq);
7473GEN_SPEFPUOP_COMP_32(efststgt);
7474GEN_SPEFPUOP_COMP_32(efststlt);
7475GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
7476
7477/* Opcodes definitions */
05332d70 7478GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
0487d6a8
JM
7479GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
7480GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
7481GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
7482GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
7483GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
7484GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
7485GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
7486GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
7487GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
9ceb2a77
TS
7488GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
7489GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
0487d6a8
JM
7490GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
7491GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
7492
7493/* Double precision floating-point operations */
7494/* Arithmetic */
1c97856d
AJ
7495GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7496GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7497GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7498GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7499static always_inline void gen_efdabs (DisasContext *ctx)
7500{
7501 if (unlikely(!ctx->spe_enabled)) {
7502 GEN_EXCP_NO_AP(ctx);
7503 return;
7504 }
7505#if defined(TARGET_PPC64)
7506 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7507#else
7508 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7509#endif
7510}
7511static always_inline void gen_efdnabs (DisasContext *ctx)
7512{
7513 if (unlikely(!ctx->spe_enabled)) {
7514 GEN_EXCP_NO_AP(ctx);
7515 return;
7516 }
7517#if defined(TARGET_PPC64)
7518 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7519#else
7520 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7521#endif
7522}
7523static always_inline void gen_efdneg (DisasContext *ctx)
7524{
7525 if (unlikely(!ctx->spe_enabled)) {
7526 GEN_EXCP_NO_AP(ctx);
7527 return;
7528 }
7529#if defined(TARGET_PPC64)
7530 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7531#else
7532 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7533#endif
7534}
7535
0487d6a8 7536/* Conversion */
1c97856d
AJ
7537GEN_SPEFPUOP_CONV_64_32(efdcfui);
7538GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7539GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7540GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7541GEN_SPEFPUOP_CONV_32_64(efdctui);
7542GEN_SPEFPUOP_CONV_32_64(efdctsi);
7543GEN_SPEFPUOP_CONV_32_64(efdctuf);
7544GEN_SPEFPUOP_CONV_32_64(efdctsf);
7545GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7546GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7547GEN_SPEFPUOP_CONV_64_32(efdcfs);
7548GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7549GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7550GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7551GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 7552
0487d6a8 7553/* Comparison */
1c97856d
AJ
7554GEN_SPEFPUOP_COMP_64(efdcmpgt);
7555GEN_SPEFPUOP_COMP_64(efdcmplt);
7556GEN_SPEFPUOP_COMP_64(efdcmpeq);
7557GEN_SPEFPUOP_COMP_64(efdtstgt);
7558GEN_SPEFPUOP_COMP_64(efdtstlt);
7559GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
7560
7561/* Opcodes definitions */
7562GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
7563GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
7564GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
7565GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
7566GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
7567GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
7568GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
7569GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
7570GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
7571GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
7572GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
7573GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
7574GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
7575GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
7576GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
7577GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
0487d6a8 7578
79aceca5
FB
7579/* End opcode list */
7580GEN_OPCODE_MARK(end);
7581
3fc6c082 7582#include "translate_init.c"
0411a972 7583#include "helper_regs.h"
79aceca5 7584
9a64fbe4 7585/*****************************************************************************/
3fc6c082 7586/* Misc PowerPC helpers */
36081602
JM
7587void cpu_dump_state (CPUState *env, FILE *f,
7588 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7589 int flags)
79aceca5 7590{
3fc6c082
FB
7591#define RGPL 4
7592#define RFPL 4
3fc6c082 7593
79aceca5
FB
7594 int i;
7595
077fc206 7596 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
3d7b417e 7597 env->nip, env->lr, env->ctr, env->xer);
6b542af7
JM
7598 cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
7599 env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
d9bce9d9 7600#if !defined(NO_TIMER_DUMP)
077fc206 7601 cpu_fprintf(f, "TB %08x %08x "
76a66253
JM
7602#if !defined(CONFIG_USER_ONLY)
7603 "DECR %08x"
7604#endif
7605 "\n",
077fc206 7606 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
7607#if !defined(CONFIG_USER_ONLY)
7608 , cpu_ppc_load_decr(env)
7609#endif
7610 );
077fc206 7611#endif
76a66253 7612 for (i = 0; i < 32; i++) {
3fc6c082
FB
7613 if ((i & (RGPL - 1)) == 0)
7614 cpu_fprintf(f, "GPR%02d", i);
6b542af7 7615 cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
3fc6c082 7616 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 7617 cpu_fprintf(f, "\n");
76a66253 7618 }
3fc6c082 7619 cpu_fprintf(f, "CR ");
76a66253 7620 for (i = 0; i < 8; i++)
7fe48483
FB
7621 cpu_fprintf(f, "%01x", env->crf[i]);
7622 cpu_fprintf(f, " [");
76a66253
JM
7623 for (i = 0; i < 8; i++) {
7624 char a = '-';
7625 if (env->crf[i] & 0x08)
7626 a = 'L';
7627 else if (env->crf[i] & 0x04)
7628 a = 'G';
7629 else if (env->crf[i] & 0x02)
7630 a = 'E';
7fe48483 7631 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 7632 }
6b542af7 7633 cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
3fc6c082
FB
7634 for (i = 0; i < 32; i++) {
7635 if ((i & (RFPL - 1)) == 0)
7636 cpu_fprintf(f, "FPR%02d", i);
26a76461 7637 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 7638 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 7639 cpu_fprintf(f, "\n");
79aceca5 7640 }
f2e63a42 7641#if !defined(CONFIG_USER_ONLY)
6b542af7 7642 cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
3fc6c082 7643 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
f2e63a42 7644#endif
79aceca5 7645
3fc6c082
FB
7646#undef RGPL
7647#undef RFPL
79aceca5
FB
7648}
7649
76a66253
JM
7650void cpu_dump_statistics (CPUState *env, FILE*f,
7651 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7652 int flags)
7653{
7654#if defined(DO_PPC_STATISTICS)
7655 opc_handler_t **t1, **t2, **t3, *handler;
7656 int op1, op2, op3;
7657
7658 t1 = env->opcodes;
7659 for (op1 = 0; op1 < 64; op1++) {
7660 handler = t1[op1];
7661 if (is_indirect_opcode(handler)) {
7662 t2 = ind_table(handler);
7663 for (op2 = 0; op2 < 32; op2++) {
7664 handler = t2[op2];
7665 if (is_indirect_opcode(handler)) {
7666 t3 = ind_table(handler);
7667 for (op3 = 0; op3 < 32; op3++) {
7668 handler = t3[op3];
7669 if (handler->count == 0)
7670 continue;
7671 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
7672 "%016llx %lld\n",
7673 op1, op2, op3, op1, (op3 << 5) | op2,
7674 handler->oname,
7675 handler->count, handler->count);
7676 }
7677 } else {
7678 if (handler->count == 0)
7679 continue;
7680 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
7681 "%016llx %lld\n",
7682 op1, op2, op1, op2, handler->oname,
7683 handler->count, handler->count);
7684 }
7685 }
7686 } else {
7687 if (handler->count == 0)
7688 continue;
7689 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
7690 op1, op1, handler->oname,
7691 handler->count, handler->count);
7692 }
7693 }
7694#endif
7695}
7696
9a64fbe4 7697/*****************************************************************************/
2cfc5f17
TS
7698static always_inline void gen_intermediate_code_internal (CPUState *env,
7699 TranslationBlock *tb,
7700 int search_pc)
79aceca5 7701{
9fddaa0c 7702 DisasContext ctx, *ctxp = &ctx;
79aceca5 7703 opc_handler_t **table, *handler;
0fa85d43 7704 target_ulong pc_start;
79aceca5 7705 uint16_t *gen_opc_end;
056401ea 7706 int supervisor, little_endian;
a1d1bb31 7707 CPUBreakpoint *bp;
79aceca5 7708 int j, lj = -1;
2e70f6ef
PB
7709 int num_insns;
7710 int max_insns;
79aceca5
FB
7711
7712 pc_start = tb->pc;
79aceca5 7713 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7c58044c
JM
7714#if defined(OPTIMIZE_FPRF_UPDATE)
7715 gen_fprf_ptr = gen_fprf_buf;
7716#endif
046d6672 7717 ctx.nip = pc_start;
79aceca5 7718 ctx.tb = tb;
e1833e1f 7719 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 7720 ctx.spr_cb = env->spr_cb;
6ebbf390
JM
7721 supervisor = env->mmu_idx;
7722#if !defined(CONFIG_USER_ONLY)
2857068e 7723 ctx.supervisor = supervisor;
d9bce9d9 7724#endif
056401ea 7725 little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
d9bce9d9
JM
7726#if defined(TARGET_PPC64)
7727 ctx.sf_mode = msr_sf;
056401ea 7728 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
2857068e 7729#else
056401ea 7730 ctx.mem_idx = (supervisor << 1) | little_endian;
9a64fbe4 7731#endif
3cc62370 7732 ctx.fpu_enabled = msr_fp;
a9d9eb8f 7733 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
7734 ctx.spe_enabled = msr_spe;
7735 else
7736 ctx.spe_enabled = 0;
a9d9eb8f
JM
7737 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7738 ctx.altivec_enabled = msr_vr;
7739 else
7740 ctx.altivec_enabled = 0;
d26bfc9a 7741 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 7742 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 7743 else
8cbcb4fa 7744 ctx.singlestep_enabled = 0;
d26bfc9a 7745 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa
AJ
7746 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
7747 if (unlikely(env->singlestep_enabled))
7748 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
3fc6c082 7749#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
7750 /* Single step trace mode */
7751 msr_se = 1;
7752#endif
2e70f6ef
PB
7753 num_insns = 0;
7754 max_insns = tb->cflags & CF_COUNT_MASK;
7755 if (max_insns == 0)
7756 max_insns = CF_COUNT_MASK;
7757
7758 gen_icount_start();
9a64fbe4 7759 /* Set env in case of segfault during code fetch */
e1833e1f 7760 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
c0ce998e
AL
7761 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7762 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 7763 if (bp->pc == ctx.nip) {
5fafdf24 7764 gen_update_nip(&ctx, ctx.nip);
64adab3f 7765 gen_helper_raise_debug();
ea4e754f
FB
7766 break;
7767 }
7768 }
7769 }
76a66253 7770 if (unlikely(search_pc)) {
79aceca5
FB
7771 j = gen_opc_ptr - gen_opc_buf;
7772 if (lj < j) {
7773 lj++;
7774 while (lj < j)
7775 gen_opc_instr_start[lj++] = 0;
046d6672 7776 gen_opc_pc[lj] = ctx.nip;
79aceca5 7777 gen_opc_instr_start[lj] = 1;
2e70f6ef 7778 gen_opc_icount[lj] = num_insns;
79aceca5
FB
7779 }
7780 }
9fddaa0c
FB
7781#if defined PPC_DEBUG_DISAS
7782 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 7783 fprintf(logfile, "----------------\n");
1b9eb036 7784 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
0411a972 7785 ctx.nip, supervisor, (int)msr_ir);
9a64fbe4
FB
7786 }
7787#endif
2e70f6ef
PB
7788 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7789 gen_io_start();
056401ea
JM
7790 if (unlikely(little_endian)) {
7791 ctx.opcode = bswap32(ldl_code(ctx.nip));
7792 } else {
7793 ctx.opcode = ldl_code(ctx.nip);
111bfab3 7794 }
9fddaa0c
FB
7795#if defined PPC_DEBUG_DISAS
7796 if (loglevel & CPU_LOG_TB_IN_ASM) {
111bfab3 7797 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 7798 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
056401ea 7799 opc3(ctx.opcode), little_endian ? "little" : "big");
79aceca5
FB
7800 }
7801#endif
046d6672 7802 ctx.nip += 4;
3fc6c082 7803 table = env->opcodes;
2e70f6ef 7804 num_insns++;
79aceca5
FB
7805 handler = table[opc1(ctx.opcode)];
7806 if (is_indirect_opcode(handler)) {
7807 table = ind_table(handler);
7808 handler = table[opc2(ctx.opcode)];
7809 if (is_indirect_opcode(handler)) {
7810 table = ind_table(handler);
7811 handler = table[opc3(ctx.opcode)];
7812 }
7813 }
7814 /* Is opcode *REALLY* valid ? */
76a66253 7815 if (unlikely(handler->handler == &gen_invalid)) {
4a057712 7816 if (loglevel != 0) {
76a66253 7817 fprintf(logfile, "invalid/unsupported opcode: "
6b542af7 7818 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
76a66253 7819 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7820 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa
FB
7821 } else {
7822 printf("invalid/unsupported opcode: "
6b542af7 7823 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
4b3686fa 7824 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7825 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa 7826 }
76a66253
JM
7827 } else {
7828 if (unlikely((ctx.opcode & handler->inval) != 0)) {
4a057712 7829 if (loglevel != 0) {
79aceca5 7830 fprintf(logfile, "invalid bits: %08x for opcode: "
6b542af7 7831 "%02x - %02x - %02x (%08x) " ADDRX "\n",
79aceca5
FB
7832 ctx.opcode & handler->inval, opc1(ctx.opcode),
7833 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7834 ctx.opcode, ctx.nip - 4);
9a64fbe4
FB
7835 } else {
7836 printf("invalid bits: %08x for opcode: "
6b542af7 7837 "%02x - %02x - %02x (%08x) " ADDRX "\n",
76a66253
JM
7838 ctx.opcode & handler->inval, opc1(ctx.opcode),
7839 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7840 ctx.opcode, ctx.nip - 4);
76a66253 7841 }
e1833e1f 7842 GEN_EXCP_INVAL(ctxp);
4b3686fa 7843 break;
79aceca5 7844 }
79aceca5 7845 }
4b3686fa 7846 (*(handler->handler))(&ctx);
76a66253
JM
7847#if defined(DO_PPC_STATISTICS)
7848 handler->count++;
7849#endif
9a64fbe4 7850 /* Check trace mode exceptions */
8cbcb4fa
AJ
7851 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
7852 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
7853 ctx.exception != POWERPC_SYSCALL &&
7854 ctx.exception != POWERPC_EXCP_TRAP &&
7855 ctx.exception != POWERPC_EXCP_BRANCH)) {
e1833e1f 7856 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
d26bfc9a 7857 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
2e70f6ef
PB
7858 (env->singlestep_enabled) ||
7859 num_insns >= max_insns)) {
d26bfc9a
JM
7860 /* if we reach a page boundary or are single stepping, stop
7861 * generation
7862 */
8dd4983c 7863 break;
76a66253 7864 }
3fc6c082
FB
7865#if defined (DO_SINGLE_STEP)
7866 break;
7867#endif
7868 }
2e70f6ef
PB
7869 if (tb->cflags & CF_LAST_IO)
7870 gen_io_end();
e1833e1f 7871 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 7872 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 7873 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8cbcb4fa
AJ
7874 if (unlikely(env->singlestep_enabled)) {
7875 gen_update_nip(&ctx, ctx.nip);
64adab3f 7876 gen_helper_raise_debug();
8cbcb4fa 7877 }
76a66253 7878 /* Generate the return instruction */
57fec1fe 7879 tcg_gen_exit_tb(0);
9a64fbe4 7880 }
2e70f6ef 7881 gen_icount_end(tb, num_insns);
79aceca5 7882 *gen_opc_ptr = INDEX_op_end;
76a66253 7883 if (unlikely(search_pc)) {
9a64fbe4
FB
7884 j = gen_opc_ptr - gen_opc_buf;
7885 lj++;
7886 while (lj <= j)
7887 gen_opc_instr_start[lj++] = 0;
9a64fbe4 7888 } else {
046d6672 7889 tb->size = ctx.nip - pc_start;
2e70f6ef 7890 tb->icount = num_insns;
9a64fbe4 7891 }
d9bce9d9 7892#if defined(DEBUG_DISAS)
9fddaa0c 7893 if (loglevel & CPU_LOG_TB_CPU) {
9a64fbe4 7894 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7fe48483 7895 cpu_dump_state(env, logfile, fprintf, 0);
9fddaa0c
FB
7896 }
7897 if (loglevel & CPU_LOG_TB_IN_ASM) {
76a66253 7898 int flags;
237c0af0 7899 flags = env->bfd_mach;
056401ea 7900 flags |= little_endian << 16;
0fa85d43 7901 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
76a66253 7902 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
79aceca5 7903 fprintf(logfile, "\n");
9fddaa0c 7904 }
79aceca5 7905#endif
79aceca5
FB
7906}
7907
2cfc5f17 7908void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5 7909{
2cfc5f17 7910 gen_intermediate_code_internal(env, tb, 0);
79aceca5
FB
7911}
7912
2cfc5f17 7913void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5 7914{
2cfc5f17 7915 gen_intermediate_code_internal(env, tb, 1);
79aceca5 7916}
d2856f1a
AJ
7917
7918void gen_pc_load(CPUState *env, TranslationBlock *tb,
7919 unsigned long searched_pc, int pc_pos, void *puc)
7920{
d2856f1a 7921 env->nip = gen_opc_pc[pc_pos];
d2856f1a 7922}