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