]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
target-ppc: convert POWER2 load/store instructions to TCG
[qemu.git] / target-ppc / translate.c
CommitLineData
79aceca5 1/*
3fc6c082 2 * PowerPC emulation for qemu: main translation routines.
5fafdf24 3 *
76a66253 4 * Copyright (c) 2003-2007 Jocelyn Mayer
79aceca5
FB
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
c6a1c22b
FB
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
79aceca5 26#include "cpu.h"
c6a1c22b 27#include "exec-all.h"
79aceca5 28#include "disas.h"
57fec1fe 29#include "tcg-op.h"
ca10f867 30#include "qemu-common.h"
79aceca5 31
a7812ae4
PB
32#include "helper.h"
33#define GEN_HELPER 1
34#include "helper.h"
35
8cbcb4fa
AJ
36#define CPU_SINGLE_STEP 0x1
37#define CPU_BRANCH_STEP 0x2
38#define GDBSTUB_SINGLE_STEP 0x4
39
a750fc0b 40/* Include definitions for instructions classes and implementations flags */
79aceca5 41//#define DO_SINGLE_STEP
9fddaa0c 42//#define PPC_DEBUG_DISAS
76a66253 43//#define DO_PPC_STATISTICS
7c58044c 44//#define OPTIMIZE_FPRF_UPDATE
79aceca5 45
a750fc0b
JM
46/*****************************************************************************/
47/* Code translation helpers */
c53be334 48
f78fb44e 49/* global register indexes */
a7812ae4 50static TCGv_ptr cpu_env;
1d542695 51static char cpu_reg_names[10*3 + 22*4 /* GPR */
f78fb44e 52#if !defined(TARGET_PPC64)
1d542695 53 + 10*4 + 22*5 /* SPE GPRh */
f78fb44e 54#endif
a5e26afa 55 + 10*4 + 22*5 /* FPR */
47e4661c
AJ
56 + 2*(10*6 + 22*7) /* AVRh, AVRl */
57 + 8*5 /* CRF */];
f78fb44e
AJ
58static TCGv cpu_gpr[32];
59#if !defined(TARGET_PPC64)
60static TCGv cpu_gprh[32];
61#endif
a7812ae4
PB
62static TCGv_i64 cpu_fpr[32];
63static TCGv_i64 cpu_avrh[32], cpu_avrl[32];
64static TCGv_i32 cpu_crf[8];
bd568f18 65static TCGv cpu_nip;
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 }
f78fb44e 4951 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4952 gen_op_602_mfrom();
f78fb44e 4953 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
4954#endif
4955}
4956
4957/* 602 - 603 - G2 TLB management */
4958/* tlbld */
c7697e1f 4959GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
4960{
4961#if defined(CONFIG_USER_ONLY)
e1833e1f 4962 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4963#else
4964 if (unlikely(!ctx->supervisor)) {
e1833e1f 4965 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4966 return;
4967 }
f78fb44e 4968 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
76a66253 4969 gen_op_6xx_tlbld();
76a66253
JM
4970#endif
4971}
4972
4973/* tlbli */
c7697e1f 4974GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
4975{
4976#if defined(CONFIG_USER_ONLY)
e1833e1f 4977 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4978#else
4979 if (unlikely(!ctx->supervisor)) {
e1833e1f 4980 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4981 return;
4982 }
f78fb44e 4983 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
76a66253 4984 gen_op_6xx_tlbli();
76a66253
JM
4985#endif
4986}
4987
7dbe11ac
JM
4988/* 74xx TLB management */
4989/* tlbld */
c7697e1f 4990GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
4991{
4992#if defined(CONFIG_USER_ONLY)
4993 GEN_EXCP_PRIVOPC(ctx);
4994#else
4995 if (unlikely(!ctx->supervisor)) {
4996 GEN_EXCP_PRIVOPC(ctx);
4997 return;
4998 }
f78fb44e 4999 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5000 gen_op_74xx_tlbld();
5001#endif
5002}
5003
5004/* tlbli */
c7697e1f 5005GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
5006{
5007#if defined(CONFIG_USER_ONLY)
5008 GEN_EXCP_PRIVOPC(ctx);
5009#else
5010 if (unlikely(!ctx->supervisor)) {
5011 GEN_EXCP_PRIVOPC(ctx);
5012 return;
5013 }
f78fb44e 5014 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5015 gen_op_74xx_tlbli();
5016#endif
5017}
5018
76a66253
JM
5019/* POWER instructions not in PowerPC 601 */
5020/* clf */
5021GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
5022{
5023 /* Cache line flush: implemented as no-op */
5024}
5025
5026/* cli */
5027GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
5028{
7f75ffd3 5029 /* Cache line invalidate: privileged and treated as no-op */
76a66253 5030#if defined(CONFIG_USER_ONLY)
e1833e1f 5031 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5032#else
5033 if (unlikely(!ctx->supervisor)) {
e1833e1f 5034 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5035 return;
5036 }
5037#endif
5038}
5039
5040/* dclst */
5041GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
5042{
5043 /* Data cache line store: treated as no-op */
5044}
5045
5046GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
5047{
5048#if defined(CONFIG_USER_ONLY)
e1833e1f 5049 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5050#else
5051 if (unlikely(!ctx->supervisor)) {
e1833e1f 5052 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5053 return;
5054 }
5055 int ra = rA(ctx->opcode);
5056 int rd = rD(ctx->opcode);
5057
e2be8d8d 5058 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5059 gen_op_POWER_mfsri();
f78fb44e 5060 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
76a66253 5061 if (ra != 0 && ra != rd)
f78fb44e 5062 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
76a66253
JM
5063#endif
5064}
5065
5066GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5067{
5068#if defined(CONFIG_USER_ONLY)
e1833e1f 5069 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5070#else
5071 if (unlikely(!ctx->supervisor)) {
e1833e1f 5072 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5073 return;
5074 }
e2be8d8d 5075 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5076 gen_op_POWER_rac();
f78fb44e 5077 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5078#endif
5079}
5080
5081GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
5082{
5083#if defined(CONFIG_USER_ONLY)
e1833e1f 5084 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5085#else
5086 if (unlikely(!ctx->supervisor)) {
e1833e1f 5087 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5088 return;
5089 }
5090 gen_op_POWER_rfsvc();
e1833e1f 5091 GEN_SYNC(ctx);
76a66253
JM
5092#endif
5093}
5094
5095/* svc is not implemented for now */
5096
5097/* POWER2 specific instructions */
5098/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5099
5100/* lfq */
5101GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5102{
01a4afeb
AJ
5103 int rd = rD(ctx->opcode);
5104 TCGv t0 = tcg_temp_new();
5105 gen_addr_imm_index(t0, ctx, 0);
5106 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5107 tcg_gen_addi_tl(t0, t0, 8);
5108 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5109 tcg_temp_free(t0);
76a66253
JM
5110}
5111
5112/* lfqu */
5113GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5114{
5115 int ra = rA(ctx->opcode);
01a4afeb
AJ
5116 int rd = rD(ctx->opcode);
5117 TCGv t0 = tcg_temp_new();
5118 TCGv t1 = tcg_temp_new();
5119 gen_addr_imm_index(t0, ctx, 0);
5120 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5121 tcg_gen_addi_tl(t1, t0, 8);
5122 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5123 if (ra != 0)
01a4afeb
AJ
5124 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5125 tcg_temp_free(t0);
5126 tcg_temp_free(t1);
76a66253
JM
5127}
5128
5129/* lfqux */
5130GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
5131{
5132 int ra = rA(ctx->opcode);
01a4afeb
AJ
5133 int rd = rD(ctx->opcode);
5134 TCGv t0 = tcg_temp_new();
5135 TCGv t1 = tcg_temp_new();
5136 gen_addr_reg_index(t0, ctx);
5137 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5138 tcg_gen_addi_tl(t1, t0, 8);
5139 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5140 if (ra != 0)
01a4afeb
AJ
5141 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5142 tcg_temp_free(t0);
5143 tcg_temp_free(t1);
76a66253
JM
5144}
5145
5146/* lfqx */
5147GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
5148{
01a4afeb
AJ
5149 int rd = rD(ctx->opcode);
5150 TCGv t0 = tcg_temp_new();
5151 gen_addr_reg_index(t0, ctx);
5152 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5153 tcg_gen_addi_tl(t0, t0, 8);
5154 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5155 tcg_temp_free(t0);
76a66253
JM
5156}
5157
5158/* stfq */
5159GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5160{
01a4afeb
AJ
5161 int rd = rD(ctx->opcode);
5162 TCGv t0 = tcg_temp_new();
5163 gen_addr_imm_index(t0, ctx, 0);
5164 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5165 tcg_gen_addi_tl(t0, t0, 8);
5166 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5167 tcg_temp_free(t0);
76a66253
JM
5168}
5169
5170/* stfqu */
5171GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5172{
5173 int ra = rA(ctx->opcode);
01a4afeb
AJ
5174 int rd = rD(ctx->opcode);
5175 TCGv t0 = tcg_temp_new();
5176 TCGv t1 = tcg_temp_new();
5177 gen_addr_imm_index(t0, ctx, 0);
5178 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5179 tcg_gen_addi_tl(t1, t0, 8);
5180 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5181 if (ra != 0)
01a4afeb
AJ
5182 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5183 tcg_temp_free(t0);
5184 tcg_temp_free(t1);
76a66253
JM
5185}
5186
5187/* stfqux */
5188GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
5189{
5190 int ra = rA(ctx->opcode);
01a4afeb
AJ
5191 int rd = rD(ctx->opcode);
5192 TCGv t0 = tcg_temp_new();
5193 TCGv t1 = tcg_temp_new();
5194 gen_addr_reg_index(t0, ctx);
5195 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5196 tcg_gen_addi_tl(t1, t0, 8);
5197 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5198 if (ra != 0)
01a4afeb
AJ
5199 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5200 tcg_temp_free(t0);
5201 tcg_temp_free(t1);
76a66253
JM
5202}
5203
5204/* stfqx */
5205GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
5206{
01a4afeb
AJ
5207 int rd = rD(ctx->opcode);
5208 TCGv t0 = tcg_temp_new();
5209 gen_addr_reg_index(t0, ctx);
5210 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5211 tcg_gen_addi_tl(t0, t0, 8);
5212 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5213 tcg_temp_free(t0);
76a66253
JM
5214}
5215
5216/* BookE specific instructions */
2662a059 5217/* XXX: not implemented on 440 ? */
05332d70 5218GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
76a66253
JM
5219{
5220 /* XXX: TODO */
e1833e1f 5221 GEN_EXCP_INVAL(ctx);
76a66253
JM
5222}
5223
2662a059 5224/* XXX: not implemented on 440 ? */
05332d70 5225GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
76a66253
JM
5226{
5227#if defined(CONFIG_USER_ONLY)
e1833e1f 5228 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5229#else
5230 if (unlikely(!ctx->supervisor)) {
e1833e1f 5231 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5232 return;
5233 }
e2be8d8d 5234 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5235 /* Use the same micro-ops as for tlbie */
d9bce9d9
JM
5236#if defined(TARGET_PPC64)
5237 if (ctx->sf_mode)
5238 gen_op_tlbie_64();
5239 else
5240#endif
5241 gen_op_tlbie();
76a66253
JM
5242#endif
5243}
5244
5245/* All 405 MAC instructions are translated here */
b068d6a7
JM
5246static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5247 int opc2, int opc3,
5248 int ra, int rb, int rt, int Rc)
76a66253 5249{
182608d4
AJ
5250 TCGv t0, t1;
5251
a7812ae4
PB
5252 t0 = tcg_temp_local_new();
5253 t1 = tcg_temp_local_new();
182608d4 5254
76a66253
JM
5255 switch (opc3 & 0x0D) {
5256 case 0x05:
5257 /* macchw - macchw. - macchwo - macchwo. */
5258 /* macchws - macchws. - macchwso - macchwso. */
5259 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5260 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5261 /* mulchw - mulchw. */
182608d4
AJ
5262 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5263 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5264 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5265 break;
5266 case 0x04:
5267 /* macchwu - macchwu. - macchwuo - macchwuo. */
5268 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5269 /* mulchwu - mulchwu. */
182608d4
AJ
5270 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5271 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5272 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5273 break;
5274 case 0x01:
5275 /* machhw - machhw. - machhwo - machhwo. */
5276 /* machhws - machhws. - machhwso - machhwso. */
5277 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5278 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5279 /* mulhhw - mulhhw. */
182608d4
AJ
5280 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5281 tcg_gen_ext16s_tl(t0, t0);
5282 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5283 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5284 break;
5285 case 0x00:
5286 /* machhwu - machhwu. - machhwuo - machhwuo. */
5287 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5288 /* mulhhwu - mulhhwu. */
182608d4
AJ
5289 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5290 tcg_gen_ext16u_tl(t0, t0);
5291 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5292 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5293 break;
5294 case 0x0D:
5295 /* maclhw - maclhw. - maclhwo - maclhwo. */
5296 /* maclhws - maclhws. - maclhwso - maclhwso. */
5297 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5298 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5299 /* mullhw - mullhw. */
182608d4
AJ
5300 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5301 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5302 break;
5303 case 0x0C:
5304 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5305 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5306 /* mullhwu - mullhwu. */
182608d4
AJ
5307 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5308 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5309 break;
5310 }
76a66253 5311 if (opc2 & 0x04) {
182608d4
AJ
5312 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5313 tcg_gen_mul_tl(t1, t0, t1);
5314 if (opc2 & 0x02) {
5315 /* nmultiply-and-accumulate (0x0E) */
5316 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5317 } else {
5318 /* multiply-and-accumulate (0x0C) */
5319 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5320 }
5321
5322 if (opc3 & 0x12) {
5323 /* Check overflow and/or saturate */
5324 int l1 = gen_new_label();
5325
5326 if (opc3 & 0x10) {
5327 /* Start with XER OV disabled, the most likely case */
5328 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5329 }
5330 if (opc3 & 0x01) {
5331 /* Signed */
5332 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5333 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5334 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5335 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5336 if (opc3 & 0x02) {
182608d4
AJ
5337 /* Saturate */
5338 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5339 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5340 }
5341 } else {
5342 /* Unsigned */
5343 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5344 if (opc3 & 0x02) {
182608d4
AJ
5345 /* Saturate */
5346 tcg_gen_movi_tl(t0, UINT32_MAX);
5347 }
5348 }
5349 if (opc3 & 0x10) {
5350 /* Check overflow */
5351 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5352 }
5353 gen_set_label(l1);
5354 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5355 }
5356 } else {
5357 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5358 }
182608d4
AJ
5359 tcg_temp_free(t0);
5360 tcg_temp_free(t1);
76a66253
JM
5361 if (unlikely(Rc) != 0) {
5362 /* Update Rc0 */
182608d4 5363 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5364 }
5365}
5366
a750fc0b
JM
5367#define GEN_MAC_HANDLER(name, opc2, opc3) \
5368GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
76a66253
JM
5369{ \
5370 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5371 rD(ctx->opcode), Rc(ctx->opcode)); \
5372}
5373
5374/* macchw - macchw. */
a750fc0b 5375GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5376/* macchwo - macchwo. */
a750fc0b 5377GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5378/* macchws - macchws. */
a750fc0b 5379GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5380/* macchwso - macchwso. */
a750fc0b 5381GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5382/* macchwsu - macchwsu. */
a750fc0b 5383GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5384/* macchwsuo - macchwsuo. */
a750fc0b 5385GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5386/* macchwu - macchwu. */
a750fc0b 5387GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5388/* macchwuo - macchwuo. */
a750fc0b 5389GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5390/* machhw - machhw. */
a750fc0b 5391GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5392/* machhwo - machhwo. */
a750fc0b 5393GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5394/* machhws - machhws. */
a750fc0b 5395GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5396/* machhwso - machhwso. */
a750fc0b 5397GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5398/* machhwsu - machhwsu. */
a750fc0b 5399GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5400/* machhwsuo - machhwsuo. */
a750fc0b 5401GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5402/* machhwu - machhwu. */
a750fc0b 5403GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5404/* machhwuo - machhwuo. */
a750fc0b 5405GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5406/* maclhw - maclhw. */
a750fc0b 5407GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5408/* maclhwo - maclhwo. */
a750fc0b 5409GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5410/* maclhws - maclhws. */
a750fc0b 5411GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5412/* maclhwso - maclhwso. */
a750fc0b 5413GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5414/* maclhwu - maclhwu. */
a750fc0b 5415GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5416/* maclhwuo - maclhwuo. */
a750fc0b 5417GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5418/* maclhwsu - maclhwsu. */
a750fc0b 5419GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5420/* maclhwsuo - maclhwsuo. */
a750fc0b 5421GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5422/* nmacchw - nmacchw. */
a750fc0b 5423GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5424/* nmacchwo - nmacchwo. */
a750fc0b 5425GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5426/* nmacchws - nmacchws. */
a750fc0b 5427GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5428/* nmacchwso - nmacchwso. */
a750fc0b 5429GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5430/* nmachhw - nmachhw. */
a750fc0b 5431GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5432/* nmachhwo - nmachhwo. */
a750fc0b 5433GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5434/* nmachhws - nmachhws. */
a750fc0b 5435GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5436/* nmachhwso - nmachhwso. */
a750fc0b 5437GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5438/* nmaclhw - nmaclhw. */
a750fc0b 5439GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5440/* nmaclhwo - nmaclhwo. */
a750fc0b 5441GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5442/* nmaclhws - nmaclhws. */
a750fc0b 5443GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5444/* nmaclhwso - nmaclhwso. */
a750fc0b 5445GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5446
5447/* mulchw - mulchw. */
a750fc0b 5448GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5449/* mulchwu - mulchwu. */
a750fc0b 5450GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5451/* mulhhw - mulhhw. */
a750fc0b 5452GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5453/* mulhhwu - mulhhwu. */
a750fc0b 5454GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5455/* mullhw - mullhw. */
a750fc0b 5456GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5457/* mullhwu - mullhwu. */
a750fc0b 5458GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5459
5460/* mfdcr */
05332d70 5461GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
76a66253
JM
5462{
5463#if defined(CONFIG_USER_ONLY)
e1833e1f 5464 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5465#else
5466 uint32_t dcrn = SPR(ctx->opcode);
5467
5468 if (unlikely(!ctx->supervisor)) {
e1833e1f 5469 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5470 return;
5471 }
86c581dc 5472 tcg_gen_movi_tl(cpu_T[0], dcrn);
a42bd6cc 5473 gen_op_load_dcr();
f78fb44e 5474 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5475#endif
5476}
5477
5478/* mtdcr */
05332d70 5479GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
76a66253
JM
5480{
5481#if defined(CONFIG_USER_ONLY)
e1833e1f 5482 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5483#else
5484 uint32_t dcrn = SPR(ctx->opcode);
5485
5486 if (unlikely(!ctx->supervisor)) {
e1833e1f 5487 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5488 return;
5489 }
86c581dc 5490 tcg_gen_movi_tl(cpu_T[0], dcrn);
f78fb44e 5491 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a42bd6cc
JM
5492 gen_op_store_dcr();
5493#endif
5494}
5495
5496/* mfdcrx */
2662a059 5497/* XXX: not implemented on 440 ? */
05332d70 5498GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5499{
5500#if defined(CONFIG_USER_ONLY)
e1833e1f 5501 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5502#else
5503 if (unlikely(!ctx->supervisor)) {
e1833e1f 5504 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5505 return;
5506 }
f78fb44e 5507 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a42bd6cc 5508 gen_op_load_dcr();
f78fb44e 5509 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
a750fc0b 5510 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5511#endif
5512}
5513
5514/* mtdcrx */
2662a059 5515/* XXX: not implemented on 440 ? */
05332d70 5516GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5517{
5518#if defined(CONFIG_USER_ONLY)
e1833e1f 5519 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5520#else
5521 if (unlikely(!ctx->supervisor)) {
e1833e1f 5522 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5523 return;
5524 }
f78fb44e
AJ
5525 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5526 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a42bd6cc 5527 gen_op_store_dcr();
a750fc0b 5528 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5529#endif
5530}
5531
a750fc0b
JM
5532/* mfdcrux (PPC 460) : user-mode access to DCR */
5533GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5534{
f78fb44e 5535 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5536 gen_op_load_dcr();
f78fb44e 5537 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
a750fc0b
JM
5538 /* Note: Rc update flag set leads to undefined state of Rc0 */
5539}
5540
5541/* mtdcrux (PPC 460) : user-mode access to DCR */
5542GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5543{
f78fb44e
AJ
5544 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5545 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
5546 gen_op_store_dcr();
5547 /* Note: Rc update flag set leads to undefined state of Rc0 */
5548}
5549
76a66253
JM
5550/* dccci */
5551GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5552{
5553#if defined(CONFIG_USER_ONLY)
e1833e1f 5554 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5555#else
5556 if (unlikely(!ctx->supervisor)) {
e1833e1f 5557 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5558 return;
5559 }
5560 /* interpreted as no-op */
5561#endif
5562}
5563
5564/* dcread */
5565GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5566{
5567#if defined(CONFIG_USER_ONLY)
e1833e1f 5568 GEN_EXCP_PRIVOPC(ctx);
76a66253 5569#else
b61f2753 5570 TCGv EA, val;
76a66253 5571 if (unlikely(!ctx->supervisor)) {
e1833e1f 5572 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5573 return;
5574 }
a7812ae4 5575 EA = tcg_temp_new();
a7859e89 5576 gen_set_access_type(ACCESS_CACHE);
b61f2753 5577 gen_addr_reg_index(EA, ctx);
a7812ae4 5578 val = tcg_temp_new();
b61f2753
AJ
5579 gen_qemu_ld32u(val, EA, ctx->mem_idx);
5580 tcg_temp_free(val);
5581 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5582 tcg_temp_free(EA);
76a66253
JM
5583#endif
5584}
5585
5586/* icbt */
c7697e1f 5587GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
76a66253
JM
5588{
5589 /* interpreted as no-op */
5590 /* XXX: specification say this is treated as a load by the MMU
5591 * but does not generate any exception
5592 */
5593}
5594
5595/* iccci */
5596GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5597{
5598#if defined(CONFIG_USER_ONLY)
e1833e1f 5599 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5600#else
5601 if (unlikely(!ctx->supervisor)) {
e1833e1f 5602 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5603 return;
5604 }
5605 /* interpreted as no-op */
5606#endif
5607}
5608
5609/* icread */
5610GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5611{
5612#if defined(CONFIG_USER_ONLY)
e1833e1f 5613 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5614#else
5615 if (unlikely(!ctx->supervisor)) {
e1833e1f 5616 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5617 return;
5618 }
5619 /* interpreted as no-op */
5620#endif
5621}
5622
5623/* rfci (supervisor only) */
c7697e1f 5624GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
a42bd6cc
JM
5625{
5626#if defined(CONFIG_USER_ONLY)
e1833e1f 5627 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5628#else
5629 if (unlikely(!ctx->supervisor)) {
e1833e1f 5630 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5631 return;
5632 }
5633 /* Restore CPU state */
5634 gen_op_40x_rfci();
e1833e1f 5635 GEN_SYNC(ctx);
a42bd6cc
JM
5636#endif
5637}
5638
5639GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5640{
5641#if defined(CONFIG_USER_ONLY)
e1833e1f 5642 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5643#else
5644 if (unlikely(!ctx->supervisor)) {
e1833e1f 5645 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5646 return;
5647 }
5648 /* Restore CPU state */
5649 gen_op_rfci();
e1833e1f 5650 GEN_SYNC(ctx);
a42bd6cc
JM
5651#endif
5652}
5653
5654/* BookE specific */
2662a059 5655/* XXX: not implemented on 440 ? */
05332d70 5656GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
76a66253
JM
5657{
5658#if defined(CONFIG_USER_ONLY)
e1833e1f 5659 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5660#else
5661 if (unlikely(!ctx->supervisor)) {
e1833e1f 5662 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5663 return;
5664 }
5665 /* Restore CPU state */
a42bd6cc 5666 gen_op_rfdi();
e1833e1f 5667 GEN_SYNC(ctx);
76a66253
JM
5668#endif
5669}
5670
2662a059 5671/* XXX: not implemented on 440 ? */
a750fc0b 5672GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
a42bd6cc
JM
5673{
5674#if defined(CONFIG_USER_ONLY)
e1833e1f 5675 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5676#else
5677 if (unlikely(!ctx->supervisor)) {
e1833e1f 5678 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5679 return;
5680 }
5681 /* Restore CPU state */
5682 gen_op_rfmci();
e1833e1f 5683 GEN_SYNC(ctx);
a42bd6cc
JM
5684#endif
5685}
5eb7995e 5686
d9bce9d9 5687/* TLB management - PowerPC 405 implementation */
76a66253 5688/* tlbre */
c7697e1f 5689GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
76a66253
JM
5690{
5691#if defined(CONFIG_USER_ONLY)
e1833e1f 5692 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5693#else
5694 if (unlikely(!ctx->supervisor)) {
e1833e1f 5695 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5696 return;
5697 }
5698 switch (rB(ctx->opcode)) {
5699 case 0:
f78fb44e 5700 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5701 gen_op_4xx_tlbre_hi();
f78fb44e 5702 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5703 break;
5704 case 1:
f78fb44e 5705 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5706 gen_op_4xx_tlbre_lo();
f78fb44e 5707 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5708 break;
5709 default:
e1833e1f 5710 GEN_EXCP_INVAL(ctx);
76a66253 5711 break;
9a64fbe4 5712 }
76a66253
JM
5713#endif
5714}
5715
d9bce9d9 5716/* tlbsx - tlbsx. */
c7697e1f 5717GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
76a66253
JM
5718{
5719#if defined(CONFIG_USER_ONLY)
e1833e1f 5720 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5721#else
5722 if (unlikely(!ctx->supervisor)) {
e1833e1f 5723 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5724 return;
5725 }
e2be8d8d 5726 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5727 gen_op_4xx_tlbsx();
76a66253 5728 if (Rc(ctx->opcode))
daf4f96e 5729 gen_op_4xx_tlbsx_check();
f78fb44e 5730 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 5731#endif
79aceca5
FB
5732}
5733
76a66253 5734/* tlbwe */
c7697e1f 5735GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
79aceca5 5736{
76a66253 5737#if defined(CONFIG_USER_ONLY)
e1833e1f 5738 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5739#else
5740 if (unlikely(!ctx->supervisor)) {
e1833e1f 5741 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5742 return;
5743 }
5744 switch (rB(ctx->opcode)) {
5745 case 0:
f78fb44e
AJ
5746 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5747 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5748 gen_op_4xx_tlbwe_hi();
5749 break;
5750 case 1:
f78fb44e
AJ
5751 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5752 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5753 gen_op_4xx_tlbwe_lo();
5754 break;
5755 default:
e1833e1f 5756 GEN_EXCP_INVAL(ctx);
76a66253 5757 break;
9a64fbe4 5758 }
76a66253
JM
5759#endif
5760}
5761
a4bb6c3e 5762/* TLB management - PowerPC 440 implementation */
5eb7995e 5763/* tlbre */
c7697e1f 5764GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5765{
5766#if defined(CONFIG_USER_ONLY)
e1833e1f 5767 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5768#else
5769 if (unlikely(!ctx->supervisor)) {
e1833e1f 5770 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5771 return;
5772 }
5773 switch (rB(ctx->opcode)) {
5774 case 0:
5eb7995e 5775 case 1:
5eb7995e 5776 case 2:
f78fb44e 5777 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a4bb6c3e 5778 gen_op_440_tlbre(rB(ctx->opcode));
f78fb44e 5779 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5780 break;
5781 default:
e1833e1f 5782 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5783 break;
5784 }
5785#endif
5786}
5787
5788/* tlbsx - tlbsx. */
c7697e1f 5789GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5eb7995e
JM
5790{
5791#if defined(CONFIG_USER_ONLY)
e1833e1f 5792 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5793#else
5794 if (unlikely(!ctx->supervisor)) {
e1833e1f 5795 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5796 return;
5797 }
e2be8d8d 5798 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5799 gen_op_440_tlbsx();
5eb7995e 5800 if (Rc(ctx->opcode))
daf4f96e 5801 gen_op_4xx_tlbsx_check();
f78fb44e 5802 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5803#endif
5804}
5805
5806/* tlbwe */
c7697e1f 5807GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5808{
5809#if defined(CONFIG_USER_ONLY)
e1833e1f 5810 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5811#else
5812 if (unlikely(!ctx->supervisor)) {
e1833e1f 5813 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5814 return;
5815 }
5816 switch (rB(ctx->opcode)) {
5817 case 0:
5eb7995e 5818 case 1:
5eb7995e 5819 case 2:
f78fb44e
AJ
5820 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5821 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a4bb6c3e 5822 gen_op_440_tlbwe(rB(ctx->opcode));
5eb7995e
JM
5823 break;
5824 default:
e1833e1f 5825 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5826 break;
5827 }
5828#endif
5829}
5830
76a66253 5831/* wrtee */
05332d70 5832GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
76a66253
JM
5833{
5834#if defined(CONFIG_USER_ONLY)
e1833e1f 5835 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5836#else
5837 if (unlikely(!ctx->supervisor)) {
e1833e1f 5838 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5839 return;
5840 }
f78fb44e 5841 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
a42bd6cc 5842 gen_op_wrte();
dee96f6c
JM
5843 /* Stop translation to have a chance to raise an exception
5844 * if we just set msr_ee to 1
5845 */
e1833e1f 5846 GEN_STOP(ctx);
76a66253
JM
5847#endif
5848}
5849
5850/* wrteei */
05332d70 5851GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
76a66253
JM
5852{
5853#if defined(CONFIG_USER_ONLY)
e1833e1f 5854 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5855#else
5856 if (unlikely(!ctx->supervisor)) {
e1833e1f 5857 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5858 return;
5859 }
86c581dc 5860 tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
a42bd6cc 5861 gen_op_wrte();
dee96f6c
JM
5862 /* Stop translation to have a chance to raise an exception
5863 * if we just set msr_ee to 1
5864 */
e1833e1f 5865 GEN_STOP(ctx);
76a66253
JM
5866#endif
5867}
5868
08e46e54 5869/* PowerPC 440 specific instructions */
76a66253
JM
5870/* dlmzb */
5871GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5872{
f78fb44e
AJ
5873 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
5874 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 5875 gen_op_440_dlmzb();
f78fb44e 5876 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
3d7b417e
AJ
5877 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
5878 tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
76a66253
JM
5879 if (Rc(ctx->opcode)) {
5880 gen_op_440_dlmzb_update_Rc();
a7812ae4
PB
5881 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_T[0]);
5882 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 0xf);
76a66253
JM
5883 }
5884}
5885
5886/* mbar replaces eieio on 440 */
5887GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5888{
5889 /* interpreted as no-op */
5890}
5891
5892/* msync replaces sync on 440 */
0db1b20e 5893GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
76a66253
JM
5894{
5895 /* interpreted as no-op */
5896}
5897
5898/* icbt */
c7697e1f 5899GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
76a66253
JM
5900{
5901 /* interpreted as no-op */
5902 /* XXX: specification say this is treated as a load by the MMU
5903 * but does not generate any exception
5904 */
79aceca5
FB
5905}
5906
a9d9eb8f
JM
5907/*** Altivec vector extension ***/
5908/* Altivec registers moves */
a9d9eb8f 5909
a9d9eb8f 5910#define GEN_VR_LDX(name, opc2, opc3) \
fe1e5c53 5911GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
a9d9eb8f 5912{ \
fe1e5c53 5913 TCGv EA; \
a9d9eb8f
JM
5914 if (unlikely(!ctx->altivec_enabled)) { \
5915 GEN_EXCP_NO_VR(ctx); \
5916 return; \
5917 } \
fe1e5c53
AJ
5918 EA = tcg_temp_new(); \
5919 gen_addr_reg_index(EA, ctx); \
5920 tcg_gen_andi_tl(EA, EA, ~0xf); \
5921 if (ctx->mem_idx & 1) { \
5922 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5923 tcg_gen_addi_tl(EA, EA, 8); \
5924 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5925 } else { \
5926 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5927 tcg_gen_addi_tl(EA, EA, 8); \
5928 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5929 } \
5930 tcg_temp_free(EA); \
a9d9eb8f
JM
5931}
5932
5933#define GEN_VR_STX(name, opc2, opc3) \
5934GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5935{ \
fe1e5c53 5936 TCGv EA; \
a9d9eb8f
JM
5937 if (unlikely(!ctx->altivec_enabled)) { \
5938 GEN_EXCP_NO_VR(ctx); \
5939 return; \
5940 } \
fe1e5c53
AJ
5941 EA = tcg_temp_new(); \
5942 gen_addr_reg_index(EA, ctx); \
5943 tcg_gen_andi_tl(EA, EA, ~0xf); \
5944 if (ctx->mem_idx & 1) { \
5945 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5946 tcg_gen_addi_tl(EA, EA, 8); \
5947 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5948 } else { \
5949 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5950 tcg_gen_addi_tl(EA, EA, 8); \
5951 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5952 } \
5953 tcg_temp_free(EA); \
a9d9eb8f
JM
5954}
5955
fe1e5c53 5956GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 5957/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 5958GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 5959
fe1e5c53 5960GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 5961/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 5962GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 5963
0487d6a8 5964/*** SPE extension ***/
0487d6a8 5965/* Register moves */
3cd7d1dd 5966
a7812ae4 5967static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
f78fb44e
AJ
5968#if defined(TARGET_PPC64)
5969 tcg_gen_mov_i64(t, cpu_gpr[reg]);
5970#else
36aa55dc 5971 tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
3cd7d1dd 5972#endif
f78fb44e 5973}
3cd7d1dd 5974
a7812ae4 5975static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
f78fb44e
AJ
5976#if defined(TARGET_PPC64)
5977 tcg_gen_mov_i64(cpu_gpr[reg], t);
5978#else
a7812ae4 5979 TCGv_i64 tmp = tcg_temp_new_i64();
f78fb44e 5980 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
f78fb44e
AJ
5981 tcg_gen_shri_i64(tmp, t, 32);
5982 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
a7812ae4 5983 tcg_temp_free_i64(tmp);
3cd7d1dd 5984#endif
f78fb44e 5985}
3cd7d1dd 5986
0487d6a8
JM
5987#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5988GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5989{ \
5990 if (Rc(ctx->opcode)) \
5991 gen_##name1(ctx); \
5992 else \
5993 gen_##name0(ctx); \
5994}
5995
5996/* Handler for undefined SPE opcodes */
b068d6a7 5997static always_inline void gen_speundef (DisasContext *ctx)
0487d6a8 5998{
e1833e1f 5999 GEN_EXCP_INVAL(ctx);
0487d6a8
JM
6000}
6001
57951c27
AJ
6002/* SPE logic */
6003#if defined(TARGET_PPC64)
6004#define GEN_SPEOP_LOGIC2(name, tcg_op) \
b068d6a7 6005static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6006{ \
6007 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6008 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6009 return; \
6010 } \
57951c27
AJ
6011 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6012 cpu_gpr[rB(ctx->opcode)]); \
6013}
6014#else
6015#define GEN_SPEOP_LOGIC2(name, tcg_op) \
6016static always_inline void gen_##name (DisasContext *ctx) \
6017{ \
6018 if (unlikely(!ctx->spe_enabled)) { \
6019 GEN_EXCP_NO_AP(ctx); \
6020 return; \
6021 } \
6022 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6023 cpu_gpr[rB(ctx->opcode)]); \
6024 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6025 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6026}
57951c27
AJ
6027#endif
6028
6029GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6030GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6031GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6032GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6033GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6034GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6035GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6036GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 6037
57951c27
AJ
6038/* SPE logic immediate */
6039#if defined(TARGET_PPC64)
6040#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
3d3a6a0a
AJ
6041static always_inline void gen_##name (DisasContext *ctx) \
6042{ \
6043 if (unlikely(!ctx->spe_enabled)) { \
6044 GEN_EXCP_NO_AP(ctx); \
6045 return; \
6046 } \
a7812ae4
PB
6047 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6048 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6049 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6050 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6051 tcg_opi(t0, t0, rB(ctx->opcode)); \
6052 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6053 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6054 tcg_temp_free_i64(t2); \
57951c27
AJ
6055 tcg_opi(t1, t1, rB(ctx->opcode)); \
6056 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6057 tcg_temp_free_i32(t0); \
6058 tcg_temp_free_i32(t1); \
3d3a6a0a 6059}
57951c27
AJ
6060#else
6061#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
b068d6a7 6062static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6063{ \
6064 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6065 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6066 return; \
6067 } \
57951c27
AJ
6068 tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6069 rB(ctx->opcode)); \
6070 tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6071 rB(ctx->opcode)); \
0487d6a8 6072}
57951c27
AJ
6073#endif
6074GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6075GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6076GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6077GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 6078
57951c27
AJ
6079/* SPE arithmetic */
6080#if defined(TARGET_PPC64)
6081#define GEN_SPEOP_ARITH1(name, tcg_op) \
b068d6a7 6082static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6083{ \
6084 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6085 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6086 return; \
6087 } \
a7812ae4
PB
6088 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6089 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6090 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6091 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6092 tcg_op(t0, t0); \
6093 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6094 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6095 tcg_temp_free_i64(t2); \
57951c27
AJ
6096 tcg_op(t1, t1); \
6097 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6098 tcg_temp_free_i32(t0); \
6099 tcg_temp_free_i32(t1); \
0487d6a8 6100}
57951c27 6101#else
a7812ae4 6102#define GEN_SPEOP_ARITH1(name, tcg_op) \
57951c27
AJ
6103static always_inline void gen_##name (DisasContext *ctx) \
6104{ \
6105 if (unlikely(!ctx->spe_enabled)) { \
6106 GEN_EXCP_NO_AP(ctx); \
6107 return; \
6108 } \
6109 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6110 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
6111}
6112#endif
0487d6a8 6113
a7812ae4 6114static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
57951c27
AJ
6115{
6116 int l1 = gen_new_label();
6117 int l2 = gen_new_label();
0487d6a8 6118
57951c27
AJ
6119 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6120 tcg_gen_neg_i32(ret, arg1);
6121 tcg_gen_br(l2);
6122 gen_set_label(l1);
a7812ae4 6123 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
6124 gen_set_label(l2);
6125}
6126GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6127GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6128GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6129GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
a7812ae4 6130static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 6131{
57951c27
AJ
6132 tcg_gen_addi_i32(ret, arg1, 0x8000);
6133 tcg_gen_ext16u_i32(ret, ret);
6134}
6135GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
6136GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6137GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 6138
57951c27
AJ
6139#if defined(TARGET_PPC64)
6140#define GEN_SPEOP_ARITH2(name, tcg_op) \
6141static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6142{ \
6143 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6144 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6145 return; \
6146 } \
a7812ae4
PB
6147 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6148 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6149 TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6150 TCGv_i64 t3 = tcg_temp_local_new(TCG_TYPE_I64); \
57951c27
AJ
6151 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6152 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6153 tcg_op(t0, t0, t2); \
6154 tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6155 tcg_gen_trunc_i64_i32(t1, t3); \
6156 tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6157 tcg_gen_trunc_i64_i32(t2, t3); \
a7812ae4 6158 tcg_temp_free_i64(t3); \
57951c27 6159 tcg_op(t1, t1, t2); \
a7812ae4 6160 tcg_temp_free_i32(t2); \
57951c27 6161 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6162 tcg_temp_free_i32(t0); \
6163 tcg_temp_free_i32(t1); \
0487d6a8 6164}
57951c27
AJ
6165#else
6166#define GEN_SPEOP_ARITH2(name, tcg_op) \
6167static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6168{ \
6169 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6170 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6171 return; \
6172 } \
57951c27
AJ
6173 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6174 cpu_gpr[rB(ctx->opcode)]); \
6175 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6176 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6177}
57951c27 6178#endif
0487d6a8 6179
a7812ae4 6180static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6181{
a7812ae4 6182 TCGv_i32 t0;
57951c27 6183 int l1, l2;
0487d6a8 6184
57951c27
AJ
6185 l1 = gen_new_label();
6186 l2 = gen_new_label();
a7812ae4 6187 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6188 /* No error here: 6 bits are used */
6189 tcg_gen_andi_i32(t0, arg2, 0x3F);
6190 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6191 tcg_gen_shr_i32(ret, arg1, t0);
6192 tcg_gen_br(l2);
6193 gen_set_label(l1);
6194 tcg_gen_movi_i32(ret, 0);
6195 tcg_gen_br(l2);
a7812ae4 6196 tcg_temp_free_i32(t0);
57951c27
AJ
6197}
6198GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
a7812ae4 6199static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6200{
a7812ae4 6201 TCGv_i32 t0;
57951c27
AJ
6202 int l1, l2;
6203
6204 l1 = gen_new_label();
6205 l2 = gen_new_label();
a7812ae4 6206 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6207 /* No error here: 6 bits are used */
6208 tcg_gen_andi_i32(t0, arg2, 0x3F);
6209 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6210 tcg_gen_sar_i32(ret, arg1, t0);
6211 tcg_gen_br(l2);
6212 gen_set_label(l1);
6213 tcg_gen_movi_i32(ret, 0);
6214 tcg_gen_br(l2);
a7812ae4 6215 tcg_temp_free_i32(t0);
57951c27
AJ
6216}
6217GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
a7812ae4 6218static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6219{
a7812ae4 6220 TCGv_i32 t0;
57951c27
AJ
6221 int l1, l2;
6222
6223 l1 = gen_new_label();
6224 l2 = gen_new_label();
a7812ae4 6225 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6226 /* No error here: 6 bits are used */
6227 tcg_gen_andi_i32(t0, arg2, 0x3F);
6228 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6229 tcg_gen_shl_i32(ret, arg1, t0);
6230 tcg_gen_br(l2);
6231 gen_set_label(l1);
6232 tcg_gen_movi_i32(ret, 0);
6233 tcg_gen_br(l2);
a7812ae4 6234 tcg_temp_free_i32(t0);
57951c27
AJ
6235}
6236GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
a7812ae4 6237static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6238{
a7812ae4 6239 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
6240 tcg_gen_andi_i32(t0, arg2, 0x1F);
6241 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 6242 tcg_temp_free_i32(t0);
57951c27
AJ
6243}
6244GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6245static always_inline void gen_evmergehi (DisasContext *ctx)
6246{
6247 if (unlikely(!ctx->spe_enabled)) {
6248 GEN_EXCP_NO_AP(ctx);
6249 return;
6250 }
6251#if defined(TARGET_PPC64)
a7812ae4
PB
6252 TCGv t0 = tcg_temp_new();
6253 TCGv t1 = tcg_temp_new();
57951c27
AJ
6254 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6255 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6256 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6257 tcg_temp_free(t0);
6258 tcg_temp_free(t1);
6259#else
6260 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6261 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6262#endif
6263}
6264GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
a7812ae4 6265static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 6266{
57951c27
AJ
6267 tcg_gen_sub_i32(ret, arg2, arg1);
6268}
6269GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 6270
57951c27
AJ
6271/* SPE arithmetic immediate */
6272#if defined(TARGET_PPC64)
6273#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6274static always_inline void gen_##name (DisasContext *ctx) \
6275{ \
6276 if (unlikely(!ctx->spe_enabled)) { \
6277 GEN_EXCP_NO_AP(ctx); \
6278 return; \
6279 } \
a7812ae4
PB
6280 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6281 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6282 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6283 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6284 tcg_op(t0, t0, rA(ctx->opcode)); \
6285 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6286 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6287 tcg_temp_free_i64(t2); \
57951c27
AJ
6288 tcg_op(t1, t1, rA(ctx->opcode)); \
6289 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6290 tcg_temp_free_i32(t0); \
6291 tcg_temp_free_i32(t1); \
57951c27
AJ
6292}
6293#else
6294#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6295static always_inline void gen_##name (DisasContext *ctx) \
6296{ \
6297 if (unlikely(!ctx->spe_enabled)) { \
6298 GEN_EXCP_NO_AP(ctx); \
6299 return; \
6300 } \
6301 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
6302 rA(ctx->opcode)); \
6303 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
6304 rA(ctx->opcode)); \
6305}
6306#endif
6307GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6308GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6309
6310/* SPE comparison */
6311#if defined(TARGET_PPC64)
6312#define GEN_SPEOP_COMP(name, tcg_cond) \
6313static always_inline void gen_##name (DisasContext *ctx) \
6314{ \
6315 if (unlikely(!ctx->spe_enabled)) { \
6316 GEN_EXCP_NO_AP(ctx); \
6317 return; \
6318 } \
6319 int l1 = gen_new_label(); \
6320 int l2 = gen_new_label(); \
6321 int l3 = gen_new_label(); \
6322 int l4 = gen_new_label(); \
a7812ae4
PB
6323 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6324 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6325 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6326 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6327 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
6328 tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
a7812ae4 6329 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
6330 tcg_gen_br(l2); \
6331 gen_set_label(l1); \
6332 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6333 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6334 gen_set_label(l2); \
6335 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6336 tcg_gen_trunc_i64_i32(t0, t2); \
6337 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6338 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6339 tcg_temp_free_i64(t2); \
57951c27
AJ
6340 tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
6341 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6342 ~(CRF_CH | CRF_CH_AND_CL)); \
6343 tcg_gen_br(l4); \
6344 gen_set_label(l3); \
6345 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6346 CRF_CH | CRF_CH_OR_CL); \
6347 gen_set_label(l4); \
a7812ae4
PB
6348 tcg_temp_free_i32(t0); \
6349 tcg_temp_free_i32(t1); \
57951c27
AJ
6350}
6351#else
6352#define GEN_SPEOP_COMP(name, tcg_cond) \
6353static always_inline void gen_##name (DisasContext *ctx) \
6354{ \
6355 if (unlikely(!ctx->spe_enabled)) { \
6356 GEN_EXCP_NO_AP(ctx); \
6357 return; \
6358 } \
6359 int l1 = gen_new_label(); \
6360 int l2 = gen_new_label(); \
6361 int l3 = gen_new_label(); \
6362 int l4 = gen_new_label(); \
6363 \
6364 tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
6365 cpu_gpr[rB(ctx->opcode)], l1); \
6366 tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
6367 tcg_gen_br(l2); \
6368 gen_set_label(l1); \
6369 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6370 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6371 gen_set_label(l2); \
6372 tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
6373 cpu_gprh[rB(ctx->opcode)], l3); \
6374 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6375 ~(CRF_CH | CRF_CH_AND_CL)); \
6376 tcg_gen_br(l4); \
6377 gen_set_label(l3); \
6378 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6379 CRF_CH | CRF_CH_OR_CL); \
6380 gen_set_label(l4); \
6381}
6382#endif
6383GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6384GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6385GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6386GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6387GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6388
6389/* SPE misc */
6390static always_inline void gen_brinc (DisasContext *ctx)
6391{
6392 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
6393 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6394 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 6395}
57951c27
AJ
6396static always_inline void gen_evmergelo (DisasContext *ctx)
6397{
6398 if (unlikely(!ctx->spe_enabled)) {
6399 GEN_EXCP_NO_AP(ctx);
6400 return;
6401 }
6402#if defined(TARGET_PPC64)
a7812ae4
PB
6403 TCGv t0 = tcg_temp_new();
6404 TCGv t1 = tcg_temp_new();
57951c27
AJ
6405 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6406 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6407 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6408 tcg_temp_free(t0);
6409 tcg_temp_free(t1);
6410#else
6411 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6412 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6413#endif
6414}
6415static always_inline void gen_evmergehilo (DisasContext *ctx)
6416{
6417 if (unlikely(!ctx->spe_enabled)) {
6418 GEN_EXCP_NO_AP(ctx);
6419 return;
6420 }
6421#if defined(TARGET_PPC64)
a7812ae4
PB
6422 TCGv t0 = tcg_temp_new();
6423 TCGv t1 = tcg_temp_new();
57951c27
AJ
6424 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6425 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6426 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6427 tcg_temp_free(t0);
6428 tcg_temp_free(t1);
6429#else
6430 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6431 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6432#endif
6433}
6434static always_inline void gen_evmergelohi (DisasContext *ctx)
6435{
6436 if (unlikely(!ctx->spe_enabled)) {
6437 GEN_EXCP_NO_AP(ctx);
6438 return;
6439 }
6440#if defined(TARGET_PPC64)
a7812ae4
PB
6441 TCGv t0 = tcg_temp_new();
6442 TCGv t1 = tcg_temp_new();
57951c27
AJ
6443 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6444 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6445 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6446 tcg_temp_free(t0);
6447 tcg_temp_free(t1);
6448#else
6449 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6450 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6451#endif
6452}
6453static always_inline void gen_evsplati (DisasContext *ctx)
6454{
38d14952 6455 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
0487d6a8 6456
57951c27 6457#if defined(TARGET_PPC64)
38d14952 6458 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6459#else
6460 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6461 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6462#endif
6463}
b068d6a7 6464static always_inline void gen_evsplatfi (DisasContext *ctx)
0487d6a8 6465{
38d14952 6466 uint64_t imm = rA(ctx->opcode) << 11;
0487d6a8 6467
57951c27 6468#if defined(TARGET_PPC64)
38d14952 6469 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6470#else
6471 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6472 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6473#endif
0487d6a8
JM
6474}
6475
57951c27
AJ
6476static always_inline void gen_evsel (DisasContext *ctx)
6477{
6478 int l1 = gen_new_label();
6479 int l2 = gen_new_label();
6480 int l3 = gen_new_label();
6481 int l4 = gen_new_label();
a7812ae4 6482 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 6483#if defined(TARGET_PPC64)
a7812ae4
PB
6484 TCGv t1 = tcg_temp_local_new();
6485 TCGv t2 = tcg_temp_local_new();
57951c27
AJ
6486#endif
6487 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
6488 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
6489#if defined(TARGET_PPC64)
6490 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6491#else
6492 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6493#endif
6494 tcg_gen_br(l2);
6495 gen_set_label(l1);
6496#if defined(TARGET_PPC64)
6497 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6498#else
6499 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6500#endif
6501 gen_set_label(l2);
6502 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
6503 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
6504#if defined(TARGET_PPC64)
6505 tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
6506#else
6507 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6508#endif
6509 tcg_gen_br(l4);
6510 gen_set_label(l3);
6511#if defined(TARGET_PPC64)
6512 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
6513#else
6514 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6515#endif
6516 gen_set_label(l4);
a7812ae4 6517 tcg_temp_free_i32(t0);
57951c27
AJ
6518#if defined(TARGET_PPC64)
6519 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
6520 tcg_temp_free(t1);
6521 tcg_temp_free(t2);
6522#endif
6523}
6524GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6525{
6526 gen_evsel(ctx);
6527}
6528GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6529{
6530 gen_evsel(ctx);
6531}
6532GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6533{
6534 gen_evsel(ctx);
6535}
6536GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6537{
6538 gen_evsel(ctx);
6539}
0487d6a8
JM
6540
6541GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6542GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
6543GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
6544GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
6545GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
6546GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
6547GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
6548GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
6549GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
6550GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
6551GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
6552GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
6553GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
6554GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
6555GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
6556GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
6557GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
6558GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
6559GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
6560GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
6561GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
6562GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
6563GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6564GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6565GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6566
6a6ae23f
AJ
6567/* SPE load and stores */
6568static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
6569{
6570 target_ulong uimm = rB(ctx->opcode);
6571
6572 if (rA(ctx->opcode) == 0)
6573 tcg_gen_movi_tl(EA, uimm << sh);
6574 else
6575 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
0487d6a8 6576}
6a6ae23f
AJ
6577
6578static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6579{
6580#if defined(TARGET_PPC64)
6581 gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6582#else
6583 TCGv_i64 t0 = tcg_temp_new_i64();
6584 gen_qemu_ld64(t0, addr, ctx->mem_idx);
6585 tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
6586 tcg_gen_shri_i64(t0, t0, 32);
6587 tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
6588 tcg_temp_free_i64(t0);
6589#endif
0487d6a8 6590}
6a6ae23f
AJ
6591
6592static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6593{
0487d6a8 6594#if defined(TARGET_PPC64)
6a6ae23f
AJ
6595 TCGv t0 = tcg_temp_new();
6596 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6597 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6598 tcg_gen_addi_tl(addr, addr, 4);
6599 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6600 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6601 tcg_temp_free(t0);
6602#else
6603 gen_qemu_ld32u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6604 tcg_gen_addi_tl(addr, addr, 4);
6605 gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6606#endif
0487d6a8 6607}
6a6ae23f
AJ
6608
6609static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6610{
6611 TCGv t0 = tcg_temp_new();
6612#if defined(TARGET_PPC64)
6613 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6614 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6615 tcg_gen_addi_tl(addr, addr, 2);
6616 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6617 tcg_gen_shli_tl(t0, t0, 32);
6618 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6619 tcg_gen_addi_tl(addr, addr, 2);
6620 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6621 tcg_gen_shli_tl(t0, t0, 16);
6622 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6623 tcg_gen_addi_tl(addr, addr, 2);
6624 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6625 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6626#else
6a6ae23f
AJ
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_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6632 tcg_gen_addi_tl(addr, addr, 2);
6633 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6634 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6635 tcg_gen_addi_tl(addr, addr, 2);
6636 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6637 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6638#endif
6a6ae23f 6639 tcg_temp_free(t0);
0487d6a8
JM
6640}
6641
6a6ae23f
AJ
6642static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6643{
6644 TCGv t0 = tcg_temp_new();
6645 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6646#if defined(TARGET_PPC64)
6647 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6648 tcg_gen_shli_tl(t0, t0, 16);
6649 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6650#else
6651 tcg_gen_shli_tl(t0, t0, 16);
6652 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6653 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6654#endif
6655 tcg_temp_free(t0);
0487d6a8
JM
6656}
6657
6a6ae23f
AJ
6658static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6659{
6660 TCGv t0 = tcg_temp_new();
6661 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6662#if defined(TARGET_PPC64)
6663 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6664 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6665#else
6666 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6667 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6668#endif
6669 tcg_temp_free(t0);
0487d6a8
JM
6670}
6671
6a6ae23f
AJ
6672static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6673{
6674 TCGv t0 = tcg_temp_new();
6675 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6676#if defined(TARGET_PPC64)
6677 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6678 tcg_gen_ext32u_tl(t0, t0);
6679 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6680#else
6681 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6682 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6683#endif
6684 tcg_temp_free(t0);
6685}
6686
6687static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6688{
6689 TCGv t0 = tcg_temp_new();
6690#if defined(TARGET_PPC64)
6691 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6692 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6693 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6694 tcg_gen_shli_tl(t0, t0, 16);
6695 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6696#else
6697 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6698 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6699 tcg_gen_addi_tl(addr, addr, 2);
6700 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6701 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6702#endif
6703 tcg_temp_free(t0);
6704}
6705
6706static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6707{
6708#if defined(TARGET_PPC64)
6709 TCGv t0 = tcg_temp_new();
6710 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6711 tcg_gen_addi_tl(addr, addr, 2);
6712 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6713 tcg_gen_shli_tl(t0, t0, 32);
6714 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6715 tcg_temp_free(t0);
6716#else
6717 gen_qemu_ld16u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6718 tcg_gen_addi_tl(addr, addr, 2);
6719 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6720#endif
6721}
6722
6723static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6724{
6725#if defined(TARGET_PPC64)
6726 TCGv t0 = tcg_temp_new();
6727 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6728 tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
6729 tcg_gen_addi_tl(addr, addr, 2);
6730 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6731 tcg_gen_shli_tl(t0, t0, 32);
6732 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6733 tcg_temp_free(t0);
6734#else
6735 gen_qemu_ld16s(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6736 tcg_gen_addi_tl(addr, addr, 2);
6737 gen_qemu_ld16s(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6738#endif
6739}
6740
6741static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6742{
6743 TCGv t0 = tcg_temp_new();
6744 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
0487d6a8 6745#if defined(TARGET_PPC64)
6a6ae23f
AJ
6746 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6747 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6748#else
6749 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6750 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6751#endif
6752 tcg_temp_free(t0);
6753}
6754
6755static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6756{
6757 TCGv t0 = tcg_temp_new();
6758#if defined(TARGET_PPC64)
6759 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6760 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6761 tcg_gen_shli_tl(t0, t0, 32);
6762 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6763 tcg_gen_addi_tl(addr, addr, 2);
6764 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6765 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6766 tcg_gen_shli_tl(t0, t0, 16);
6767 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6768#else
6769 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6770 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6771 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6772 tcg_gen_addi_tl(addr, addr, 2);
6773 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6774 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6775 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
0487d6a8 6776#endif
6a6ae23f
AJ
6777 tcg_temp_free(t0);
6778}
6779
6780static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6781{
6782#if defined(TARGET_PPC64)
6783 gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
0487d6a8 6784#else
6a6ae23f
AJ
6785 TCGv_i64 t0 = tcg_temp_new_i64();
6786 tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
6787 gen_qemu_st64(t0, addr, ctx->mem_idx);
6788 tcg_temp_free_i64(t0);
6789#endif
6790}
6791
6792static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6793{
0487d6a8 6794#if defined(TARGET_PPC64)
6a6ae23f
AJ
6795 TCGv t0 = tcg_temp_new();
6796 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6797 gen_qemu_st32(t0, addr, ctx->mem_idx);
6798 tcg_temp_free(t0);
6799#else
6800 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6801#endif
6802 tcg_gen_addi_tl(addr, addr, 4);
6803 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6804}
6805
6806static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6807{
6808 TCGv t0 = tcg_temp_new();
6809#if defined(TARGET_PPC64)
6810 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6811#else
6812 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6813#endif
6814 gen_qemu_st16(t0, addr, ctx->mem_idx);
6815 tcg_gen_addi_tl(addr, addr, 2);
6816#if defined(TARGET_PPC64)
6817 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6818 gen_qemu_st16(t0, addr, ctx->mem_idx);
6819#else
6820 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6821#endif
6822 tcg_gen_addi_tl(addr, addr, 2);
6823 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6824 gen_qemu_st16(t0, addr, ctx->mem_idx);
6825 tcg_temp_free(t0);
6826 tcg_gen_addi_tl(addr, addr, 2);
6827 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6828}
6829
6830static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6831{
6832 TCGv t0 = tcg_temp_new();
6833#if defined(TARGET_PPC64)
6834 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6835#else
6836 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6837#endif
6838 gen_qemu_st16(t0, addr, ctx->mem_idx);
6839 tcg_gen_addi_tl(addr, addr, 2);
6840 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6841 gen_qemu_st16(t0, addr, ctx->mem_idx);
6842 tcg_temp_free(t0);
6843}
6844
6845static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
6846{
6847#if defined(TARGET_PPC64)
6848 TCGv t0 = tcg_temp_new();
6849 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6850 gen_qemu_st16(t0, addr, ctx->mem_idx);
6851 tcg_temp_free(t0);
6852#else
6853 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6854#endif
6855 tcg_gen_addi_tl(addr, addr, 2);
6856 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6857}
6858
6859static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
6860{
6861#if defined(TARGET_PPC64)
6862 TCGv t0 = tcg_temp_new();
6863 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6864 gen_qemu_st32(t0, addr, ctx->mem_idx);
6865 tcg_temp_free(t0);
6866#else
6867 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6868#endif
6869}
6870
6871static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
6872{
6873 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6874}
6875
6876#define GEN_SPEOP_LDST(name, opc2, sh) \
6877GEN_HANDLER(gen_##name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \
6878{ \
6879 TCGv t0; \
6880 if (unlikely(!ctx->spe_enabled)) { \
6881 GEN_EXCP_NO_AP(ctx); \
6882 return; \
6883 } \
6884 t0 = tcg_temp_new(); \
6885 if (Rc(ctx->opcode)) { \
6886 gen_addr_spe_imm_index(t0, ctx, sh); \
6887 } else { \
6888 gen_addr_reg_index(t0, ctx); \
6889 } \
6890 gen_op_##name(ctx, t0); \
6891 tcg_temp_free(t0); \
6892}
6893
6894GEN_SPEOP_LDST(evldd, 0x00, 3);
6895GEN_SPEOP_LDST(evldw, 0x01, 3);
6896GEN_SPEOP_LDST(evldh, 0x02, 3);
6897GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
6898GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
6899GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
6900GEN_SPEOP_LDST(evlwhe, 0x08, 2);
6901GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
6902GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
6903GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
6904GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
6905
6906GEN_SPEOP_LDST(evstdd, 0x10, 3);
6907GEN_SPEOP_LDST(evstdw, 0x11, 3);
6908GEN_SPEOP_LDST(evstdh, 0x12, 3);
6909GEN_SPEOP_LDST(evstwhe, 0x18, 2);
6910GEN_SPEOP_LDST(evstwho, 0x1A, 2);
6911GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
6912GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
6913
6914/* Multiply and add - TODO */
6915#if 0
6916GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
6917GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
6918GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
6919GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
6920GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
6921GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
6922GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
6923GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
6924GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
6925GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
6926GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
6927GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
6928
6929GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
6930GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
6931GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
6932GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
6933GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
6934GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
6935GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
6936GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
6937GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
6938GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
6939GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
6940GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
6941GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
6942GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
6943
6944GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
6945GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
6946GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
6947GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
6948GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
6949GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
6950
6951GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
6952GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
6953GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
6954GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
6955GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
6956GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
6957GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
6958GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
6959GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
6960GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
6961GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
6962GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
6963
6964GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
6965GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
6966GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
6967GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
6968GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
6969
6970GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
6971GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
6972GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
6973GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
6974GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
6975GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
6976GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
6977GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
6978GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
6979GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
6980GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
6981GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
6982
6983GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
6984GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
6985GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
6986GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
6987GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
6988#endif
6989
6990/*** SPE floating-point extension ***/
1c97856d
AJ
6991#if defined(TARGET_PPC64)
6992#define GEN_SPEFPUOP_CONV_32_32(name) \
b068d6a7 6993static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8 6994{ \
1c97856d
AJ
6995 TCGv_i32 t0; \
6996 TCGv t1; \
6997 t0 = tcg_temp_new_i32(); \
6998 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6999 gen_helper_##name(t0, t0); \
7000 t1 = tcg_temp_new(); \
7001 tcg_gen_extu_i32_tl(t1, t0); \
7002 tcg_temp_free_i32(t0); \
7003 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7004 0xFFFFFFFF00000000ULL); \
7005 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7006 tcg_temp_free(t1); \
0487d6a8 7007}
1c97856d
AJ
7008#define GEN_SPEFPUOP_CONV_32_64(name) \
7009static always_inline void gen_##name (DisasContext *ctx) \
7010{ \
7011 TCGv_i32 t0; \
7012 TCGv t1; \
7013 t0 = tcg_temp_new_i32(); \
7014 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7015 t1 = tcg_temp_new(); \
7016 tcg_gen_extu_i32_tl(t1, t0); \
7017 tcg_temp_free_i32(t0); \
7018 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7019 0xFFFFFFFF00000000ULL); \
7020 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7021 tcg_temp_free(t1); \
7022}
7023#define GEN_SPEFPUOP_CONV_64_32(name) \
7024static always_inline void gen_##name (DisasContext *ctx) \
7025{ \
7026 TCGv_i32 t0 = tcg_temp_new_i32(); \
7027 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7028 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7029 tcg_temp_free_i32(t0); \
7030}
7031#define GEN_SPEFPUOP_CONV_64_64(name) \
7032static always_inline void gen_##name (DisasContext *ctx) \
7033{ \
7034 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7035}
7036#define GEN_SPEFPUOP_ARITH2_32_32(name) \
57951c27
AJ
7037static always_inline void gen_##name (DisasContext *ctx) \
7038{ \
1c97856d
AJ
7039 TCGv_i32 t0, t1; \
7040 TCGv_i64 t2; \
57951c27
AJ
7041 if (unlikely(!ctx->spe_enabled)) { \
7042 GEN_EXCP_NO_AP(ctx); \
7043 return; \
7044 } \
1c97856d
AJ
7045 t0 = tcg_temp_new_i32(); \
7046 t1 = tcg_temp_new_i32(); \
7047 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7048 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7049 gen_helper_##name(t0, t0, t1); \
7050 tcg_temp_free_i32(t1); \
7051 t2 = tcg_temp_new(); \
7052 tcg_gen_extu_i32_tl(t2, t0); \
7053 tcg_temp_free_i32(t0); \
7054 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7055 0xFFFFFFFF00000000ULL); \
7056 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7057 tcg_temp_free(t2); \
57951c27 7058}
1c97856d 7059#define GEN_SPEFPUOP_ARITH2_64_64(name) \
57951c27
AJ
7060static always_inline void gen_##name (DisasContext *ctx) \
7061{ \
7062 if (unlikely(!ctx->spe_enabled)) { \
7063 GEN_EXCP_NO_AP(ctx); \
7064 return; \
7065 } \
1c97856d
AJ
7066 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7067 cpu_gpr[rB(ctx->opcode)]); \
57951c27 7068}
1c97856d 7069#define GEN_SPEFPUOP_COMP_32(name) \
57951c27
AJ
7070static always_inline void gen_##name (DisasContext *ctx) \
7071{ \
1c97856d 7072 TCGv_i32 t0, t1; \
57951c27
AJ
7073 if (unlikely(!ctx->spe_enabled)) { \
7074 GEN_EXCP_NO_AP(ctx); \
7075 return; \
7076 } \
1c97856d
AJ
7077 t0 = tcg_temp_new_i32(); \
7078 t1 = tcg_temp_new_i32(); \
7079 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7080 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7081 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7082 tcg_temp_free_i32(t0); \
7083 tcg_temp_free_i32(t1); \
7084}
7085#define GEN_SPEFPUOP_COMP_64(name) \
7086static always_inline void gen_##name (DisasContext *ctx) \
7087{ \
7088 if (unlikely(!ctx->spe_enabled)) { \
7089 GEN_EXCP_NO_AP(ctx); \
7090 return; \
7091 } \
7092 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7093 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7094}
7095#else
7096#define GEN_SPEFPUOP_CONV_32_32(name) \
7097static always_inline void gen_##name (DisasContext *ctx) \
7098{ \
7099 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
57951c27 7100}
1c97856d
AJ
7101#define GEN_SPEFPUOP_CONV_32_64(name) \
7102static always_inline void gen_##name (DisasContext *ctx) \
7103{ \
7104 TCGv_i64 t0 = tcg_temp_new_i64(); \
7105 gen_load_gpr64(t0, rB(ctx->opcode)); \
7106 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7107 tcg_temp_free_i64(t0); \
7108}
7109#define GEN_SPEFPUOP_CONV_64_32(name) \
7110static always_inline void gen_##name (DisasContext *ctx) \
7111{ \
7112 TCGv_i64 t0 = tcg_temp_new_i64(); \
7113 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7114 gen_store_gpr64(rD(ctx->opcode), t0); \
7115 tcg_temp_free_i64(t0); \
7116}
7117#define GEN_SPEFPUOP_CONV_64_64(name) \
7118static always_inline void gen_##name (DisasContext *ctx) \
7119{ \
7120 TCGv_i64 t0 = tcg_temp_new_i64(); \
7121 gen_load_gpr64(t0, rB(ctx->opcode)); \
7122 gen_helper_##name(t0, t0); \
7123 gen_store_gpr64(rD(ctx->opcode), t0); \
7124 tcg_temp_free_i64(t0); \
7125}
7126#define GEN_SPEFPUOP_ARITH2_32_32(name) \
7127static always_inline void gen_##name (DisasContext *ctx) \
7128{ \
7129 if (unlikely(!ctx->spe_enabled)) { \
7130 GEN_EXCP_NO_AP(ctx); \
7131 return; \
7132 } \
7133 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
7134 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7135}
7136#define GEN_SPEFPUOP_ARITH2_64_64(name) \
7137static always_inline void gen_##name (DisasContext *ctx) \
7138{ \
7139 TCGv_i64 t0, t1; \
7140 if (unlikely(!ctx->spe_enabled)) { \
7141 GEN_EXCP_NO_AP(ctx); \
7142 return; \
7143 } \
7144 t0 = tcg_temp_new_i64(); \
7145 t1 = tcg_temp_new_i64(); \
7146 gen_load_gpr64(t0, rA(ctx->opcode)); \
7147 gen_load_gpr64(t1, rB(ctx->opcode)); \
7148 gen_helper_##name(t0, t0, t1); \
7149 gen_store_gpr64(rD(ctx->opcode), t0); \
7150 tcg_temp_free_i64(t0); \
7151 tcg_temp_free_i64(t1); \
7152}
7153#define GEN_SPEFPUOP_COMP_32(name) \
7154static always_inline void gen_##name (DisasContext *ctx) \
7155{ \
7156 if (unlikely(!ctx->spe_enabled)) { \
7157 GEN_EXCP_NO_AP(ctx); \
7158 return; \
7159 } \
7160 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7161 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7162}
7163#define GEN_SPEFPUOP_COMP_64(name) \
7164static always_inline void gen_##name (DisasContext *ctx) \
7165{ \
7166 TCGv_i64 t0, t1; \
7167 if (unlikely(!ctx->spe_enabled)) { \
7168 GEN_EXCP_NO_AP(ctx); \
7169 return; \
7170 } \
7171 t0 = tcg_temp_new_i64(); \
7172 t1 = tcg_temp_new_i64(); \
7173 gen_load_gpr64(t0, rA(ctx->opcode)); \
7174 gen_load_gpr64(t1, rB(ctx->opcode)); \
7175 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7176 tcg_temp_free_i64(t0); \
7177 tcg_temp_free_i64(t1); \
7178}
7179#endif
57951c27 7180
0487d6a8
JM
7181/* Single precision floating-point vectors operations */
7182/* Arithmetic */
1c97856d
AJ
7183GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7184GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7185GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7186GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7187static always_inline void gen_evfsabs (DisasContext *ctx)
7188{
7189 if (unlikely(!ctx->spe_enabled)) {
7190 GEN_EXCP_NO_AP(ctx);
7191 return;
7192 }
7193#if defined(TARGET_PPC64)
7194 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7195#else
7196 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7197 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7198#endif
7199}
7200static always_inline void gen_evfsnabs (DisasContext *ctx)
7201{
7202 if (unlikely(!ctx->spe_enabled)) {
7203 GEN_EXCP_NO_AP(ctx);
7204 return;
7205 }
7206#if defined(TARGET_PPC64)
7207 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7208#else
7209 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7210 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7211#endif
7212}
7213static always_inline void gen_evfsneg (DisasContext *ctx)
7214{
7215 if (unlikely(!ctx->spe_enabled)) {
7216 GEN_EXCP_NO_AP(ctx);
7217 return;
7218 }
7219#if defined(TARGET_PPC64)
7220 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7221#else
7222 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7223 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7224#endif
7225}
7226
0487d6a8 7227/* Conversion */
1c97856d
AJ
7228GEN_SPEFPUOP_CONV_64_64(evfscfui);
7229GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7230GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7231GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7232GEN_SPEFPUOP_CONV_64_64(evfsctui);
7233GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7234GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7235GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7236GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7237GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7238
0487d6a8 7239/* Comparison */
1c97856d
AJ
7240GEN_SPEFPUOP_COMP_64(evfscmpgt);
7241GEN_SPEFPUOP_COMP_64(evfscmplt);
7242GEN_SPEFPUOP_COMP_64(evfscmpeq);
7243GEN_SPEFPUOP_COMP_64(evfststgt);
7244GEN_SPEFPUOP_COMP_64(evfststlt);
7245GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
7246
7247/* Opcodes definitions */
7248GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
7249GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
7250GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
7251GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
7252GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
7253GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
7254GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
7255GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
7256GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
7257GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
7258GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
7259GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
7260GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
7261GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
7262
7263/* Single precision floating-point operations */
7264/* Arithmetic */
1c97856d
AJ
7265GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7266GEN_SPEFPUOP_ARITH2_32_32(efssub);
7267GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7268GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7269static always_inline void gen_efsabs (DisasContext *ctx)
7270{
7271 if (unlikely(!ctx->spe_enabled)) {
7272 GEN_EXCP_NO_AP(ctx);
7273 return;
7274 }
7275 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7276}
7277static always_inline void gen_efsnabs (DisasContext *ctx)
7278{
7279 if (unlikely(!ctx->spe_enabled)) {
7280 GEN_EXCP_NO_AP(ctx);
7281 return;
7282 }
7283 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7284}
7285static always_inline void gen_efsneg (DisasContext *ctx)
7286{
7287 if (unlikely(!ctx->spe_enabled)) {
7288 GEN_EXCP_NO_AP(ctx);
7289 return;
7290 }
7291 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7292}
7293
0487d6a8 7294/* Conversion */
1c97856d
AJ
7295GEN_SPEFPUOP_CONV_32_32(efscfui);
7296GEN_SPEFPUOP_CONV_32_32(efscfsi);
7297GEN_SPEFPUOP_CONV_32_32(efscfuf);
7298GEN_SPEFPUOP_CONV_32_32(efscfsf);
7299GEN_SPEFPUOP_CONV_32_32(efsctui);
7300GEN_SPEFPUOP_CONV_32_32(efsctsi);
7301GEN_SPEFPUOP_CONV_32_32(efsctuf);
7302GEN_SPEFPUOP_CONV_32_32(efsctsf);
7303GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7304GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7305GEN_SPEFPUOP_CONV_32_64(efscfd);
7306
0487d6a8 7307/* Comparison */
1c97856d
AJ
7308GEN_SPEFPUOP_COMP_32(efscmpgt);
7309GEN_SPEFPUOP_COMP_32(efscmplt);
7310GEN_SPEFPUOP_COMP_32(efscmpeq);
7311GEN_SPEFPUOP_COMP_32(efststgt);
7312GEN_SPEFPUOP_COMP_32(efststlt);
7313GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
7314
7315/* Opcodes definitions */
05332d70 7316GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
0487d6a8
JM
7317GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
7318GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
7319GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
7320GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
7321GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
7322GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
7323GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
7324GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
7325GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
9ceb2a77
TS
7326GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
7327GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
0487d6a8
JM
7328GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
7329GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
7330
7331/* Double precision floating-point operations */
7332/* Arithmetic */
1c97856d
AJ
7333GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7334GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7335GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7336GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7337static always_inline void gen_efdabs (DisasContext *ctx)
7338{
7339 if (unlikely(!ctx->spe_enabled)) {
7340 GEN_EXCP_NO_AP(ctx);
7341 return;
7342 }
7343#if defined(TARGET_PPC64)
7344 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7345#else
7346 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7347#endif
7348}
7349static always_inline void gen_efdnabs (DisasContext *ctx)
7350{
7351 if (unlikely(!ctx->spe_enabled)) {
7352 GEN_EXCP_NO_AP(ctx);
7353 return;
7354 }
7355#if defined(TARGET_PPC64)
7356 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7357#else
7358 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7359#endif
7360}
7361static always_inline void gen_efdneg (DisasContext *ctx)
7362{
7363 if (unlikely(!ctx->spe_enabled)) {
7364 GEN_EXCP_NO_AP(ctx);
7365 return;
7366 }
7367#if defined(TARGET_PPC64)
7368 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7369#else
7370 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7371#endif
7372}
7373
0487d6a8 7374/* Conversion */
1c97856d
AJ
7375GEN_SPEFPUOP_CONV_64_32(efdcfui);
7376GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7377GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7378GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7379GEN_SPEFPUOP_CONV_32_64(efdctui);
7380GEN_SPEFPUOP_CONV_32_64(efdctsi);
7381GEN_SPEFPUOP_CONV_32_64(efdctuf);
7382GEN_SPEFPUOP_CONV_32_64(efdctsf);
7383GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7384GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7385GEN_SPEFPUOP_CONV_64_32(efdcfs);
7386GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7387GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7388GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7389GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 7390
0487d6a8 7391/* Comparison */
1c97856d
AJ
7392GEN_SPEFPUOP_COMP_64(efdcmpgt);
7393GEN_SPEFPUOP_COMP_64(efdcmplt);
7394GEN_SPEFPUOP_COMP_64(efdcmpeq);
7395GEN_SPEFPUOP_COMP_64(efdtstgt);
7396GEN_SPEFPUOP_COMP_64(efdtstlt);
7397GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
7398
7399/* Opcodes definitions */
7400GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
7401GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
7402GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
7403GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
7404GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
7405GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
7406GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
7407GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
7408GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
7409GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
7410GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
7411GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
7412GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
7413GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
7414GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
7415GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
0487d6a8 7416
79aceca5
FB
7417/* End opcode list */
7418GEN_OPCODE_MARK(end);
7419
3fc6c082 7420#include "translate_init.c"
0411a972 7421#include "helper_regs.h"
79aceca5 7422
9a64fbe4 7423/*****************************************************************************/
3fc6c082 7424/* Misc PowerPC helpers */
36081602
JM
7425void cpu_dump_state (CPUState *env, FILE *f,
7426 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7427 int flags)
79aceca5 7428{
3fc6c082
FB
7429#define RGPL 4
7430#define RFPL 4
3fc6c082 7431
79aceca5
FB
7432 int i;
7433
077fc206 7434 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
3d7b417e 7435 env->nip, env->lr, env->ctr, env->xer);
6b542af7
JM
7436 cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
7437 env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
d9bce9d9 7438#if !defined(NO_TIMER_DUMP)
077fc206 7439 cpu_fprintf(f, "TB %08x %08x "
76a66253
JM
7440#if !defined(CONFIG_USER_ONLY)
7441 "DECR %08x"
7442#endif
7443 "\n",
077fc206 7444 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
7445#if !defined(CONFIG_USER_ONLY)
7446 , cpu_ppc_load_decr(env)
7447#endif
7448 );
077fc206 7449#endif
76a66253 7450 for (i = 0; i < 32; i++) {
3fc6c082
FB
7451 if ((i & (RGPL - 1)) == 0)
7452 cpu_fprintf(f, "GPR%02d", i);
6b542af7 7453 cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
3fc6c082 7454 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 7455 cpu_fprintf(f, "\n");
76a66253 7456 }
3fc6c082 7457 cpu_fprintf(f, "CR ");
76a66253 7458 for (i = 0; i < 8; i++)
7fe48483
FB
7459 cpu_fprintf(f, "%01x", env->crf[i]);
7460 cpu_fprintf(f, " [");
76a66253
JM
7461 for (i = 0; i < 8; i++) {
7462 char a = '-';
7463 if (env->crf[i] & 0x08)
7464 a = 'L';
7465 else if (env->crf[i] & 0x04)
7466 a = 'G';
7467 else if (env->crf[i] & 0x02)
7468 a = 'E';
7fe48483 7469 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 7470 }
6b542af7 7471 cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
3fc6c082
FB
7472 for (i = 0; i < 32; i++) {
7473 if ((i & (RFPL - 1)) == 0)
7474 cpu_fprintf(f, "FPR%02d", i);
26a76461 7475 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 7476 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 7477 cpu_fprintf(f, "\n");
79aceca5 7478 }
f2e63a42 7479#if !defined(CONFIG_USER_ONLY)
6b542af7 7480 cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
3fc6c082 7481 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
f2e63a42 7482#endif
79aceca5 7483
3fc6c082
FB
7484#undef RGPL
7485#undef RFPL
79aceca5
FB
7486}
7487
76a66253
JM
7488void cpu_dump_statistics (CPUState *env, FILE*f,
7489 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7490 int flags)
7491{
7492#if defined(DO_PPC_STATISTICS)
7493 opc_handler_t **t1, **t2, **t3, *handler;
7494 int op1, op2, op3;
7495
7496 t1 = env->opcodes;
7497 for (op1 = 0; op1 < 64; op1++) {
7498 handler = t1[op1];
7499 if (is_indirect_opcode(handler)) {
7500 t2 = ind_table(handler);
7501 for (op2 = 0; op2 < 32; op2++) {
7502 handler = t2[op2];
7503 if (is_indirect_opcode(handler)) {
7504 t3 = ind_table(handler);
7505 for (op3 = 0; op3 < 32; op3++) {
7506 handler = t3[op3];
7507 if (handler->count == 0)
7508 continue;
7509 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
7510 "%016llx %lld\n",
7511 op1, op2, op3, op1, (op3 << 5) | op2,
7512 handler->oname,
7513 handler->count, handler->count);
7514 }
7515 } else {
7516 if (handler->count == 0)
7517 continue;
7518 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
7519 "%016llx %lld\n",
7520 op1, op2, op1, op2, handler->oname,
7521 handler->count, handler->count);
7522 }
7523 }
7524 } else {
7525 if (handler->count == 0)
7526 continue;
7527 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
7528 op1, op1, handler->oname,
7529 handler->count, handler->count);
7530 }
7531 }
7532#endif
7533}
7534
9a64fbe4 7535/*****************************************************************************/
2cfc5f17
TS
7536static always_inline void gen_intermediate_code_internal (CPUState *env,
7537 TranslationBlock *tb,
7538 int search_pc)
79aceca5 7539{
9fddaa0c 7540 DisasContext ctx, *ctxp = &ctx;
79aceca5 7541 opc_handler_t **table, *handler;
0fa85d43 7542 target_ulong pc_start;
79aceca5 7543 uint16_t *gen_opc_end;
056401ea 7544 int supervisor, little_endian;
a1d1bb31 7545 CPUBreakpoint *bp;
79aceca5 7546 int j, lj = -1;
2e70f6ef
PB
7547 int num_insns;
7548 int max_insns;
79aceca5
FB
7549
7550 pc_start = tb->pc;
79aceca5 7551 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7c58044c
JM
7552#if defined(OPTIMIZE_FPRF_UPDATE)
7553 gen_fprf_ptr = gen_fprf_buf;
7554#endif
046d6672 7555 ctx.nip = pc_start;
79aceca5 7556 ctx.tb = tb;
e1833e1f 7557 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 7558 ctx.spr_cb = env->spr_cb;
6ebbf390
JM
7559 supervisor = env->mmu_idx;
7560#if !defined(CONFIG_USER_ONLY)
2857068e 7561 ctx.supervisor = supervisor;
d9bce9d9 7562#endif
056401ea 7563 little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
d9bce9d9
JM
7564#if defined(TARGET_PPC64)
7565 ctx.sf_mode = msr_sf;
056401ea 7566 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
2857068e 7567#else
056401ea 7568 ctx.mem_idx = (supervisor << 1) | little_endian;
9a64fbe4 7569#endif
d63001d1 7570 ctx.dcache_line_size = env->dcache_line_size;
3cc62370 7571 ctx.fpu_enabled = msr_fp;
a9d9eb8f 7572 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
7573 ctx.spe_enabled = msr_spe;
7574 else
7575 ctx.spe_enabled = 0;
a9d9eb8f
JM
7576 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7577 ctx.altivec_enabled = msr_vr;
7578 else
7579 ctx.altivec_enabled = 0;
d26bfc9a 7580 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 7581 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 7582 else
8cbcb4fa 7583 ctx.singlestep_enabled = 0;
d26bfc9a 7584 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa
AJ
7585 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
7586 if (unlikely(env->singlestep_enabled))
7587 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
3fc6c082 7588#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
7589 /* Single step trace mode */
7590 msr_se = 1;
7591#endif
2e70f6ef
PB
7592 num_insns = 0;
7593 max_insns = tb->cflags & CF_COUNT_MASK;
7594 if (max_insns == 0)
7595 max_insns = CF_COUNT_MASK;
7596
7597 gen_icount_start();
9a64fbe4 7598 /* Set env in case of segfault during code fetch */
e1833e1f 7599 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
c0ce998e
AL
7600 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7601 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 7602 if (bp->pc == ctx.nip) {
5fafdf24 7603 gen_update_nip(&ctx, ctx.nip);
64adab3f 7604 gen_helper_raise_debug();
ea4e754f
FB
7605 break;
7606 }
7607 }
7608 }
76a66253 7609 if (unlikely(search_pc)) {
79aceca5
FB
7610 j = gen_opc_ptr - gen_opc_buf;
7611 if (lj < j) {
7612 lj++;
7613 while (lj < j)
7614 gen_opc_instr_start[lj++] = 0;
046d6672 7615 gen_opc_pc[lj] = ctx.nip;
79aceca5 7616 gen_opc_instr_start[lj] = 1;
2e70f6ef 7617 gen_opc_icount[lj] = num_insns;
79aceca5
FB
7618 }
7619 }
9fddaa0c
FB
7620#if defined PPC_DEBUG_DISAS
7621 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 7622 fprintf(logfile, "----------------\n");
1b9eb036 7623 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
0411a972 7624 ctx.nip, supervisor, (int)msr_ir);
9a64fbe4
FB
7625 }
7626#endif
2e70f6ef
PB
7627 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7628 gen_io_start();
056401ea
JM
7629 if (unlikely(little_endian)) {
7630 ctx.opcode = bswap32(ldl_code(ctx.nip));
7631 } else {
7632 ctx.opcode = ldl_code(ctx.nip);
111bfab3 7633 }
9fddaa0c
FB
7634#if defined PPC_DEBUG_DISAS
7635 if (loglevel & CPU_LOG_TB_IN_ASM) {
111bfab3 7636 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 7637 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
056401ea 7638 opc3(ctx.opcode), little_endian ? "little" : "big");
79aceca5
FB
7639 }
7640#endif
046d6672 7641 ctx.nip += 4;
3fc6c082 7642 table = env->opcodes;
2e70f6ef 7643 num_insns++;
79aceca5
FB
7644 handler = table[opc1(ctx.opcode)];
7645 if (is_indirect_opcode(handler)) {
7646 table = ind_table(handler);
7647 handler = table[opc2(ctx.opcode)];
7648 if (is_indirect_opcode(handler)) {
7649 table = ind_table(handler);
7650 handler = table[opc3(ctx.opcode)];
7651 }
7652 }
7653 /* Is opcode *REALLY* valid ? */
76a66253 7654 if (unlikely(handler->handler == &gen_invalid)) {
4a057712 7655 if (loglevel != 0) {
76a66253 7656 fprintf(logfile, "invalid/unsupported opcode: "
6b542af7 7657 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
76a66253 7658 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7659 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa
FB
7660 } else {
7661 printf("invalid/unsupported opcode: "
6b542af7 7662 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
4b3686fa 7663 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7664 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa 7665 }
76a66253
JM
7666 } else {
7667 if (unlikely((ctx.opcode & handler->inval) != 0)) {
4a057712 7668 if (loglevel != 0) {
79aceca5 7669 fprintf(logfile, "invalid bits: %08x for opcode: "
6b542af7 7670 "%02x - %02x - %02x (%08x) " ADDRX "\n",
79aceca5
FB
7671 ctx.opcode & handler->inval, opc1(ctx.opcode),
7672 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7673 ctx.opcode, ctx.nip - 4);
9a64fbe4
FB
7674 } else {
7675 printf("invalid bits: %08x for opcode: "
6b542af7 7676 "%02x - %02x - %02x (%08x) " ADDRX "\n",
76a66253
JM
7677 ctx.opcode & handler->inval, opc1(ctx.opcode),
7678 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7679 ctx.opcode, ctx.nip - 4);
76a66253 7680 }
e1833e1f 7681 GEN_EXCP_INVAL(ctxp);
4b3686fa 7682 break;
79aceca5 7683 }
79aceca5 7684 }
4b3686fa 7685 (*(handler->handler))(&ctx);
76a66253
JM
7686#if defined(DO_PPC_STATISTICS)
7687 handler->count++;
7688#endif
9a64fbe4 7689 /* Check trace mode exceptions */
8cbcb4fa
AJ
7690 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
7691 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
7692 ctx.exception != POWERPC_SYSCALL &&
7693 ctx.exception != POWERPC_EXCP_TRAP &&
7694 ctx.exception != POWERPC_EXCP_BRANCH)) {
e1833e1f 7695 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
d26bfc9a 7696 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
2e70f6ef
PB
7697 (env->singlestep_enabled) ||
7698 num_insns >= max_insns)) {
d26bfc9a
JM
7699 /* if we reach a page boundary or are single stepping, stop
7700 * generation
7701 */
8dd4983c 7702 break;
76a66253 7703 }
3fc6c082
FB
7704#if defined (DO_SINGLE_STEP)
7705 break;
7706#endif
7707 }
2e70f6ef
PB
7708 if (tb->cflags & CF_LAST_IO)
7709 gen_io_end();
e1833e1f 7710 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 7711 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 7712 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8cbcb4fa
AJ
7713 if (unlikely(env->singlestep_enabled)) {
7714 gen_update_nip(&ctx, ctx.nip);
64adab3f 7715 gen_helper_raise_debug();
8cbcb4fa 7716 }
76a66253 7717 /* Generate the return instruction */
57fec1fe 7718 tcg_gen_exit_tb(0);
9a64fbe4 7719 }
2e70f6ef 7720 gen_icount_end(tb, num_insns);
79aceca5 7721 *gen_opc_ptr = INDEX_op_end;
76a66253 7722 if (unlikely(search_pc)) {
9a64fbe4
FB
7723 j = gen_opc_ptr - gen_opc_buf;
7724 lj++;
7725 while (lj <= j)
7726 gen_opc_instr_start[lj++] = 0;
9a64fbe4 7727 } else {
046d6672 7728 tb->size = ctx.nip - pc_start;
2e70f6ef 7729 tb->icount = num_insns;
9a64fbe4 7730 }
d9bce9d9 7731#if defined(DEBUG_DISAS)
9fddaa0c 7732 if (loglevel & CPU_LOG_TB_CPU) {
9a64fbe4 7733 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7fe48483 7734 cpu_dump_state(env, logfile, fprintf, 0);
9fddaa0c
FB
7735 }
7736 if (loglevel & CPU_LOG_TB_IN_ASM) {
76a66253 7737 int flags;
237c0af0 7738 flags = env->bfd_mach;
056401ea 7739 flags |= little_endian << 16;
0fa85d43 7740 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
76a66253 7741 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
79aceca5 7742 fprintf(logfile, "\n");
9fddaa0c 7743 }
79aceca5 7744#endif
79aceca5
FB
7745}
7746
2cfc5f17 7747void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5 7748{
2cfc5f17 7749 gen_intermediate_code_internal(env, tb, 0);
79aceca5
FB
7750}
7751
2cfc5f17 7752void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5 7753{
2cfc5f17 7754 gen_intermediate_code_internal(env, tb, 1);
79aceca5 7755}
d2856f1a
AJ
7756
7757void gen_pc_load(CPUState *env, TranslationBlock *tb,
7758 unsigned long searched_pc, int pc_pos, void *puc)
7759{
d2856f1a 7760 env->nip = gen_opc_pc[pc_pos];
d2856f1a 7761}