]> git.proxmox.com Git - qemu.git/blame - target-ppc/translate.c
target-ppc: convert load/store multiple 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 ***/
3095/* lmw */
3096GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3097{
ff4a62cd
AJ
3098 TCGv t0 = tcg_temp_new();
3099 TCGv_i32 t1 = tcg_const_i32(rD(ctx->opcode));
76a66253 3100 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3101 gen_update_nip(ctx, ctx->nip - 4);
ff4a62cd
AJ
3102 gen_addr_imm_index(t0, ctx, 0);
3103 gen_helper_lmw(t0, t1);
3104 tcg_temp_free(t0);
3105 tcg_temp_free_i32(t1);
79aceca5
FB
3106}
3107
3108/* stmw */
3109GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
3110{
ff4a62cd
AJ
3111 TCGv t0 = tcg_temp_new();
3112 TCGv_i32 t1 = tcg_const_i32(rS(ctx->opcode));
76a66253 3113 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 3114 gen_update_nip(ctx, ctx->nip - 4);
ff4a62cd
AJ
3115 gen_addr_imm_index(t0, ctx, 0);
3116 gen_helper_stmw(t0, t1);
3117 tcg_temp_free(t0);
3118 tcg_temp_free_i32(t1);
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{
931ff272
AJ
3313 TCGv_i32 t0 = tcg_temp_new_i32();
3314 tcg_gen_st_i32(t0, cpu_env, offsetof(CPUState, halted));
3315 tcg_temp_free_i32(t0);
0db1b20e 3316 /* Stop translation, as the CPU is supposed to sleep from now */
be147d08 3317 GEN_EXCP(ctx, EXCP_HLT, 1);
0db1b20e
JM
3318}
3319
79aceca5 3320/*** Floating-point load ***/
a0d7d5a7
AJ
3321#define GEN_LDF(name, ldop, opc, type) \
3322GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3323{ \
a0d7d5a7 3324 TCGv EA; \
76a66253 3325 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3326 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3327 return; \
3328 } \
a7859e89 3329 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3330 EA = tcg_temp_new(); \
3331 gen_addr_imm_index(EA, ctx, 0); \
3332 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3333 tcg_temp_free(EA); \
79aceca5
FB
3334}
3335
a0d7d5a7
AJ
3336#define GEN_LDUF(name, ldop, opc, type) \
3337GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3338{ \
a0d7d5a7 3339 TCGv EA; \
76a66253 3340 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3341 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3342 return; \
3343 } \
76a66253 3344 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3345 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3346 return; \
9a64fbe4 3347 } \
a7859e89 3348 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3349 EA = tcg_temp_new(); \
3350 gen_addr_imm_index(EA, ctx, 0); \
3351 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3352 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3353 tcg_temp_free(EA); \
79aceca5
FB
3354}
3355
a0d7d5a7
AJ
3356#define GEN_LDUXF(name, ldop, opc, type) \
3357GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
79aceca5 3358{ \
a0d7d5a7 3359 TCGv EA; \
76a66253 3360 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3361 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3362 return; \
3363 } \
76a66253 3364 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3365 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3366 return; \
9a64fbe4 3367 } \
a7859e89 3368 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3369 EA = tcg_temp_new(); \
3370 gen_addr_reg_index(EA, ctx); \
3371 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3372 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3373 tcg_temp_free(EA); \
79aceca5
FB
3374}
3375
a0d7d5a7
AJ
3376#define GEN_LDXF(name, ldop, opc2, opc3, type) \
3377GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 3378{ \
a0d7d5a7 3379 TCGv EA; \
76a66253 3380 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3381 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3382 return; \
3383 } \
a7859e89 3384 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3385 EA = tcg_temp_new(); \
3386 gen_addr_reg_index(EA, ctx); \
3387 gen_qemu_##ldop(cpu_fpr[rD(ctx->opcode)], EA, ctx->mem_idx); \
3388 tcg_temp_free(EA); \
79aceca5
FB
3389}
3390
a0d7d5a7
AJ
3391#define GEN_LDFS(name, ldop, op, type) \
3392GEN_LDF(name, ldop, op | 0x20, type); \
3393GEN_LDUF(name, ldop, op | 0x21, type); \
3394GEN_LDUXF(name, ldop, op | 0x01, type); \
3395GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
3396
3397static always_inline void gen_qemu_ld32fs(TCGv_i64 arg1, TCGv arg2, int flags)
3398{
3399 TCGv t0 = tcg_temp_new();
3400 TCGv_i32 t1 = tcg_temp_new_i32();
3401 gen_qemu_ld32u(t0, arg2, flags);
3402 tcg_gen_trunc_tl_i32(t1, t0);
3403 tcg_temp_free(t0);
3404 gen_helper_float32_to_float64(arg1, t1);
3405 tcg_temp_free_i32(t1);
3406}
79aceca5 3407
a0d7d5a7
AJ
3408 /* lfd lfdu lfdux lfdx */
3409GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT);
3410 /* lfs lfsu lfsux lfsx */
3411GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
79aceca5
FB
3412
3413/*** Floating-point store ***/
a0d7d5a7
AJ
3414#define GEN_STF(name, stop, opc, type) \
3415GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3416{ \
a0d7d5a7 3417 TCGv EA; \
76a66253 3418 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3419 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3420 return; \
3421 } \
a7859e89 3422 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3423 EA = tcg_temp_new(); \
3424 gen_addr_imm_index(EA, ctx, 0); \
3425 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3426 tcg_temp_free(EA); \
79aceca5
FB
3427}
3428
a0d7d5a7
AJ
3429#define GEN_STUF(name, stop, opc, type) \
3430GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type) \
79aceca5 3431{ \
a0d7d5a7 3432 TCGv EA; \
76a66253 3433 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3434 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3435 return; \
3436 } \
76a66253 3437 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3438 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3439 return; \
9a64fbe4 3440 } \
a7859e89 3441 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3442 EA = tcg_temp_new(); \
3443 gen_addr_imm_index(EA, ctx, 0); \
3444 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3445 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3446 tcg_temp_free(EA); \
79aceca5
FB
3447}
3448
a0d7d5a7
AJ
3449#define GEN_STUXF(name, stop, opc, type) \
3450GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type) \
79aceca5 3451{ \
a0d7d5a7 3452 TCGv EA; \
76a66253 3453 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3454 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3455 return; \
3456 } \
76a66253 3457 if (unlikely(rA(ctx->opcode) == 0)) { \
e1833e1f 3458 GEN_EXCP_INVAL(ctx); \
9fddaa0c 3459 return; \
9a64fbe4 3460 } \
a7859e89 3461 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3462 EA = tcg_temp_new(); \
3463 gen_addr_reg_index(EA, ctx); \
3464 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3465 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
3466 tcg_temp_free(EA); \
79aceca5
FB
3467}
3468
a0d7d5a7
AJ
3469#define GEN_STXF(name, stop, opc2, opc3, type) \
3470GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type) \
79aceca5 3471{ \
a0d7d5a7 3472 TCGv EA; \
76a66253 3473 if (unlikely(!ctx->fpu_enabled)) { \
e1833e1f 3474 GEN_EXCP_NO_FP(ctx); \
4ecc3190
FB
3475 return; \
3476 } \
a7859e89 3477 gen_set_access_type(ACCESS_FLOAT); \
a0d7d5a7
AJ
3478 EA = tcg_temp_new(); \
3479 gen_addr_reg_index(EA, ctx); \
3480 gen_qemu_##stop(cpu_fpr[rS(ctx->opcode)], EA, ctx->mem_idx); \
3481 tcg_temp_free(EA); \
79aceca5
FB
3482}
3483
a0d7d5a7
AJ
3484#define GEN_STFS(name, stop, op, type) \
3485GEN_STF(name, stop, op | 0x20, type); \
3486GEN_STUF(name, stop, op | 0x21, type); \
3487GEN_STUXF(name, stop, op | 0x01, type); \
3488GEN_STXF(name, stop, 0x17, op | 0x00, type)
3489
3490static always_inline void gen_qemu_st32fs(TCGv_i64 arg1, TCGv arg2, int flags)
3491{
3492 TCGv_i32 t0 = tcg_temp_new_i32();
3493 TCGv t1 = tcg_temp_new();
3494 gen_helper_float64_to_float32(t0, arg1);
3495 tcg_gen_extu_i32_tl(t1, t0);
3496 tcg_temp_free_i32(t0);
3497 gen_qemu_st32(t1, arg2, flags);
3498 tcg_temp_free(t1);
3499}
79aceca5
FB
3500
3501/* stfd stfdu stfdux stfdx */
a0d7d5a7 3502GEN_STFS(stfd, st64, 0x16, PPC_FLOAT);
79aceca5 3503/* stfs stfsu stfsux stfsx */
a0d7d5a7 3504GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
79aceca5
FB
3505
3506/* Optional: */
a0d7d5a7
AJ
3507static always_inline void gen_qemu_st32fiw(TCGv_i64 arg1, TCGv arg2, int flags)
3508{
3509 TCGv t0 = tcg_temp_new();
3510 tcg_gen_trunc_i64_tl(t0, arg1),
3511 gen_qemu_st32(t0, arg2, flags);
3512 tcg_temp_free(t0);
3513}
79aceca5 3514/* stfiwx */
a0d7d5a7 3515GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
79aceca5
FB
3516
3517/*** Branch ***/
b068d6a7
JM
3518static always_inline void gen_goto_tb (DisasContext *ctx, int n,
3519 target_ulong dest)
c1942362
FB
3520{
3521 TranslationBlock *tb;
3522 tb = ctx->tb;
a2ffb812
AJ
3523#if defined(TARGET_PPC64)
3524 if (!ctx->sf_mode)
3525 dest = (uint32_t) dest;
3526#endif
57fec1fe 3527 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
8cbcb4fa 3528 likely(!ctx->singlestep_enabled)) {
57fec1fe 3529 tcg_gen_goto_tb(n);
a2ffb812 3530 tcg_gen_movi_tl(cpu_nip, dest & ~3);
57fec1fe 3531 tcg_gen_exit_tb((long)tb + n);
c1942362 3532 } else {
a2ffb812 3533 tcg_gen_movi_tl(cpu_nip, dest & ~3);
8cbcb4fa
AJ
3534 if (unlikely(ctx->singlestep_enabled)) {
3535 if ((ctx->singlestep_enabled &
bdc4e053 3536 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
8cbcb4fa
AJ
3537 ctx->exception == POWERPC_EXCP_BRANCH) {
3538 target_ulong tmp = ctx->nip;
3539 ctx->nip = dest;
3540 GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
3541 ctx->nip = tmp;
3542 }
3543 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3544 gen_update_nip(ctx, dest);
64adab3f 3545 gen_helper_raise_debug();
8cbcb4fa
AJ
3546 }
3547 }
57fec1fe 3548 tcg_gen_exit_tb(0);
c1942362 3549 }
c53be334
FB
3550}
3551
b068d6a7 3552static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
e1833e1f
JM
3553{
3554#if defined(TARGET_PPC64)
a2ffb812
AJ
3555 if (ctx->sf_mode == 0)
3556 tcg_gen_movi_tl(cpu_lr, (uint32_t)nip);
e1833e1f
JM
3557 else
3558#endif
a2ffb812 3559 tcg_gen_movi_tl(cpu_lr, nip);
e1833e1f
JM
3560}
3561
79aceca5
FB
3562/* b ba bl bla */
3563GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3564{
76a66253 3565 target_ulong li, target;
38a64f9d 3566
8cbcb4fa 3567 ctx->exception = POWERPC_EXCP_BRANCH;
38a64f9d 3568 /* sign extend LI */
76a66253 3569#if defined(TARGET_PPC64)
d9bce9d9
JM
3570 if (ctx->sf_mode)
3571 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
3572 else
76a66253 3573#endif
d9bce9d9 3574 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
76a66253 3575 if (likely(AA(ctx->opcode) == 0))
046d6672 3576 target = ctx->nip + li - 4;
79aceca5 3577 else
9a64fbe4 3578 target = li;
e1833e1f
JM
3579 if (LK(ctx->opcode))
3580 gen_setlr(ctx, ctx->nip);
c1942362 3581 gen_goto_tb(ctx, 0, target);
79aceca5
FB
3582}
3583
e98a6e40
FB
3584#define BCOND_IM 0
3585#define BCOND_LR 1
3586#define BCOND_CTR 2
3587
b068d6a7 3588static always_inline void gen_bcond (DisasContext *ctx, int type)
d9bce9d9 3589{
d9bce9d9 3590 uint32_t bo = BO(ctx->opcode);
a2ffb812
AJ
3591 int l1 = gen_new_label();
3592 TCGv target;
e98a6e40 3593
8cbcb4fa 3594 ctx->exception = POWERPC_EXCP_BRANCH;
a2ffb812 3595 if (type == BCOND_LR || type == BCOND_CTR) {
a7812ae4 3596 target = tcg_temp_local_new();
a2ffb812
AJ
3597 if (type == BCOND_CTR)
3598 tcg_gen_mov_tl(target, cpu_ctr);
3599 else
3600 tcg_gen_mov_tl(target, cpu_lr);
e98a6e40 3601 }
e1833e1f
JM
3602 if (LK(ctx->opcode))
3603 gen_setlr(ctx, ctx->nip);
a2ffb812
AJ
3604 l1 = gen_new_label();
3605 if ((bo & 0x4) == 0) {
3606 /* Decrement and test CTR */
a7812ae4 3607 TCGv temp = tcg_temp_new();
a2ffb812
AJ
3608 if (unlikely(type == BCOND_CTR)) {
3609 GEN_EXCP_INVAL(ctx);
3610 return;
3611 }
3612 tcg_gen_subi_tl(cpu_ctr, cpu_ctr, 1);
d9bce9d9 3613#if defined(TARGET_PPC64)
a2ffb812
AJ
3614 if (!ctx->sf_mode)
3615 tcg_gen_ext32u_tl(temp, cpu_ctr);
3616 else
d9bce9d9 3617#endif
a2ffb812
AJ
3618 tcg_gen_mov_tl(temp, cpu_ctr);
3619 if (bo & 0x2) {
3620 tcg_gen_brcondi_tl(TCG_COND_NE, temp, 0, l1);
3621 } else {
3622 tcg_gen_brcondi_tl(TCG_COND_EQ, temp, 0, l1);
e98a6e40 3623 }
a7812ae4 3624 tcg_temp_free(temp);
a2ffb812
AJ
3625 }
3626 if ((bo & 0x10) == 0) {
3627 /* Test CR */
3628 uint32_t bi = BI(ctx->opcode);
3629 uint32_t mask = 1 << (3 - (bi & 0x03));
a7812ae4 3630 TCGv_i32 temp = tcg_temp_new_i32();
a2ffb812 3631
d9bce9d9 3632 if (bo & 0x8) {
a2ffb812
AJ
3633 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3634 tcg_gen_brcondi_i32(TCG_COND_EQ, temp, 0, l1);
d9bce9d9 3635 } else {
a2ffb812
AJ
3636 tcg_gen_andi_i32(temp, cpu_crf[bi >> 2], mask);
3637 tcg_gen_brcondi_i32(TCG_COND_NE, temp, 0, l1);
d9bce9d9 3638 }
a7812ae4 3639 tcg_temp_free_i32(temp);
d9bce9d9 3640 }
e98a6e40 3641 if (type == BCOND_IM) {
a2ffb812
AJ
3642 target_ulong li = (target_long)((int16_t)(BD(ctx->opcode)));
3643 if (likely(AA(ctx->opcode) == 0)) {
3644 gen_goto_tb(ctx, 0, ctx->nip + li - 4);
3645 } else {
3646 gen_goto_tb(ctx, 0, li);
3647 }
c53be334 3648 gen_set_label(l1);
c1942362 3649 gen_goto_tb(ctx, 1, ctx->nip);
e98a6e40 3650 } else {
d9bce9d9 3651#if defined(TARGET_PPC64)
a2ffb812
AJ
3652 if (!(ctx->sf_mode))
3653 tcg_gen_andi_tl(cpu_nip, target, (uint32_t)~3);
3654 else
3655#endif
3656 tcg_gen_andi_tl(cpu_nip, target, ~3);
3657 tcg_gen_exit_tb(0);
3658 gen_set_label(l1);
3659#if defined(TARGET_PPC64)
3660 if (!(ctx->sf_mode))
3661 tcg_gen_movi_tl(cpu_nip, (uint32_t)ctx->nip);
d9bce9d9
JM
3662 else
3663#endif
a2ffb812 3664 tcg_gen_movi_tl(cpu_nip, ctx->nip);
57fec1fe 3665 tcg_gen_exit_tb(0);
08e46e54 3666 }
e98a6e40
FB
3667}
3668
3669GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3b46e624 3670{
e98a6e40
FB
3671 gen_bcond(ctx, BCOND_IM);
3672}
3673
3674GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3b46e624 3675{
e98a6e40
FB
3676 gen_bcond(ctx, BCOND_CTR);
3677}
3678
3679GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3b46e624 3680{
e98a6e40
FB
3681 gen_bcond(ctx, BCOND_LR);
3682}
79aceca5
FB
3683
3684/*** Condition register logical ***/
e1571908
AJ
3685#define GEN_CRLOGIC(name, tcg_op, opc) \
3686GEN_HANDLER(name, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
79aceca5 3687{ \
fc0d441e
JM
3688 uint8_t bitmask; \
3689 int sh; \
a7812ae4 3690 TCGv_i32 t0, t1; \
fc0d441e 3691 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
a7812ae4 3692 t0 = tcg_temp_new_i32(); \
fc0d441e 3693 if (sh > 0) \
fea0c503 3694 tcg_gen_shri_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], sh); \
fc0d441e 3695 else if (sh < 0) \
fea0c503 3696 tcg_gen_shli_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2], -sh); \
e1571908 3697 else \
fea0c503 3698 tcg_gen_mov_i32(t0, cpu_crf[crbA(ctx->opcode) >> 2]); \
a7812ae4 3699 t1 = tcg_temp_new_i32(); \
fc0d441e
JM
3700 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3701 if (sh > 0) \
fea0c503 3702 tcg_gen_shri_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], sh); \
fc0d441e 3703 else if (sh < 0) \
fea0c503 3704 tcg_gen_shli_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2], -sh); \
e1571908 3705 else \
fea0c503
AJ
3706 tcg_gen_mov_i32(t1, cpu_crf[crbB(ctx->opcode) >> 2]); \
3707 tcg_op(t0, t0, t1); \
fc0d441e 3708 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
fea0c503
AJ
3709 tcg_gen_andi_i32(t0, t0, bitmask); \
3710 tcg_gen_andi_i32(t1, cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3711 tcg_gen_or_i32(cpu_crf[crbD(ctx->opcode) >> 2], t0, t1); \
a7812ae4
PB
3712 tcg_temp_free_i32(t0); \
3713 tcg_temp_free_i32(t1); \
79aceca5
FB
3714}
3715
3716/* crand */
e1571908 3717GEN_CRLOGIC(crand, tcg_gen_and_i32, 0x08);
79aceca5 3718/* crandc */
e1571908 3719GEN_CRLOGIC(crandc, tcg_gen_andc_i32, 0x04);
79aceca5 3720/* creqv */
e1571908 3721GEN_CRLOGIC(creqv, tcg_gen_eqv_i32, 0x09);
79aceca5 3722/* crnand */
e1571908 3723GEN_CRLOGIC(crnand, tcg_gen_nand_i32, 0x07);
79aceca5 3724/* crnor */
e1571908 3725GEN_CRLOGIC(crnor, tcg_gen_nor_i32, 0x01);
79aceca5 3726/* cror */
e1571908 3727GEN_CRLOGIC(cror, tcg_gen_or_i32, 0x0E);
79aceca5 3728/* crorc */
e1571908 3729GEN_CRLOGIC(crorc, tcg_gen_orc_i32, 0x0D);
79aceca5 3730/* crxor */
e1571908 3731GEN_CRLOGIC(crxor, tcg_gen_xor_i32, 0x06);
79aceca5
FB
3732/* mcrf */
3733GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3734{
47e4661c 3735 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
79aceca5
FB
3736}
3737
3738/*** System linkage ***/
3739/* rfi (supervisor only) */
76a66253 3740GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
79aceca5 3741{
9a64fbe4 3742#if defined(CONFIG_USER_ONLY)
e1833e1f 3743 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4
FB
3744#else
3745 /* Restore CPU state */
76a66253 3746 if (unlikely(!ctx->supervisor)) {
e1833e1f 3747 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 3748 return;
9a64fbe4 3749 }
a42bd6cc 3750 gen_op_rfi();
e1833e1f 3751 GEN_SYNC(ctx);
9a64fbe4 3752#endif
79aceca5
FB
3753}
3754
426613db 3755#if defined(TARGET_PPC64)
a750fc0b 3756GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
426613db
JM
3757{
3758#if defined(CONFIG_USER_ONLY)
e1833e1f 3759 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
3760#else
3761 /* Restore CPU state */
3762 if (unlikely(!ctx->supervisor)) {
e1833e1f 3763 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
3764 return;
3765 }
a42bd6cc 3766 gen_op_rfid();
e1833e1f 3767 GEN_SYNC(ctx);
426613db
JM
3768#endif
3769}
426613db 3770
5b8105fa 3771GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
be147d08
JM
3772{
3773#if defined(CONFIG_USER_ONLY)
3774 GEN_EXCP_PRIVOPC(ctx);
3775#else
3776 /* Restore CPU state */
3777 if (unlikely(ctx->supervisor <= 1)) {
3778 GEN_EXCP_PRIVOPC(ctx);
3779 return;
3780 }
3781 gen_op_hrfid();
3782 GEN_SYNC(ctx);
3783#endif
3784}
3785#endif
3786
79aceca5 3787/* sc */
417bf010
JM
3788#if defined(CONFIG_USER_ONLY)
3789#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3790#else
3791#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3792#endif
e1833e1f 3793GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
79aceca5 3794{
e1833e1f
JM
3795 uint32_t lev;
3796
3797 lev = (ctx->opcode >> 5) & 0x7F;
417bf010 3798 GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
79aceca5
FB
3799}
3800
3801/*** Trap ***/
3802/* tw */
76a66253 3803GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
79aceca5 3804{
cab3bee2 3805 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
a0ae05aa 3806 /* Update the nip since this might generate a trap exception */
d9bce9d9 3807 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3808 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3809 tcg_temp_free_i32(t0);
79aceca5
FB
3810}
3811
3812/* twi */
3813GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3814{
cab3bee2
AJ
3815 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3816 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3817 /* Update the nip since this might generate a trap exception */
3818 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3819 gen_helper_tw(cpu_gpr[rA(ctx->opcode)], t0, t1);
3820 tcg_temp_free(t0);
3821 tcg_temp_free_i32(t1);
79aceca5
FB
3822}
3823
d9bce9d9
JM
3824#if defined(TARGET_PPC64)
3825/* td */
3826GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3827{
cab3bee2 3828 TCGv_i32 t0 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3829 /* Update the nip since this might generate a trap exception */
3830 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3831 gen_helper_td(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], t0);
3832 tcg_temp_free_i32(t0);
d9bce9d9
JM
3833}
3834
3835/* tdi */
3836GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3837{
cab3bee2
AJ
3838 TCGv t0 = tcg_const_tl(SIMM(ctx->opcode));
3839 TCGv_i32 t1 = tcg_const_i32(TO(ctx->opcode));
d9bce9d9
JM
3840 /* Update the nip since this might generate a trap exception */
3841 gen_update_nip(ctx, ctx->nip);
cab3bee2
AJ
3842 gen_helper_td(cpu_gpr[rA(ctx->opcode)], t0, t1);
3843 tcg_temp_free(t0);
3844 tcg_temp_free_i32(t1);
d9bce9d9
JM
3845}
3846#endif
3847
79aceca5 3848/*** Processor control ***/
79aceca5
FB
3849/* mcrxr */
3850GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3851{
3d7b417e
AJ
3852 tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], cpu_xer);
3853 tcg_gen_shri_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], XER_CA);
269f3e95 3854 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
79aceca5
FB
3855}
3856
3857/* mfcr */
76a66253 3858GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
79aceca5 3859{
76a66253 3860 uint32_t crm, crn;
3b46e624 3861
76a66253
JM
3862 if (likely(ctx->opcode & 0x00100000)) {
3863 crm = CRM(ctx->opcode);
3864 if (likely((crm ^ (crm - 1)) == 0)) {
3865 crn = ffs(crm);
e1571908 3866 tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
76a66253 3867 }
d9bce9d9 3868 } else {
a7812ae4 3869 gen_helper_load_cr(cpu_gpr[rD(ctx->opcode)]);
d9bce9d9 3870 }
79aceca5
FB
3871}
3872
3873/* mfmsr */
3874GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3875{
9a64fbe4 3876#if defined(CONFIG_USER_ONLY)
e1833e1f 3877 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 3878#else
76a66253 3879 if (unlikely(!ctx->supervisor)) {
e1833e1f 3880 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 3881 return;
9a64fbe4 3882 }
6676f424 3883 gen_op_load_msr();
f78fb44e 3884 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
9a64fbe4 3885#endif
79aceca5
FB
3886}
3887
a11b8151 3888#if 1
6f2d8978 3889#define SPR_NOACCESS ((void *)(-1UL))
3fc6c082
FB
3890#else
3891static void spr_noaccess (void *opaque, int sprn)
3892{
3893 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3894 printf("ERROR: try to access SPR %d !\n", sprn);
3895}
3896#define SPR_NOACCESS (&spr_noaccess)
3897#endif
3898
79aceca5 3899/* mfspr */
b068d6a7 3900static always_inline void gen_op_mfspr (DisasContext *ctx)
79aceca5 3901{
3fc6c082 3902 void (*read_cb)(void *opaque, int sprn);
79aceca5
FB
3903 uint32_t sprn = SPR(ctx->opcode);
3904
3fc6c082 3905#if !defined(CONFIG_USER_ONLY)
be147d08
JM
3906 if (ctx->supervisor == 2)
3907 read_cb = ctx->spr_cb[sprn].hea_read;
7863667f 3908 else if (ctx->supervisor)
3fc6c082
FB
3909 read_cb = ctx->spr_cb[sprn].oea_read;
3910 else
9a64fbe4 3911#endif
3fc6c082 3912 read_cb = ctx->spr_cb[sprn].uea_read;
76a66253
JM
3913 if (likely(read_cb != NULL)) {
3914 if (likely(read_cb != SPR_NOACCESS)) {
3fc6c082 3915 (*read_cb)(ctx, sprn);
f78fb44e 3916 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3fc6c082
FB
3917 } else {
3918 /* Privilege exception */
9fceefa7
JM
3919 /* This is a hack to avoid warnings when running Linux:
3920 * this OS breaks the PowerPC virtualisation model,
3921 * allowing userland application to read the PVR
3922 */
3923 if (sprn != SPR_PVR) {
3924 if (loglevel != 0) {
6b542af7 3925 fprintf(logfile, "Trying to read privileged spr %d %03x at "
077fc206 3926 ADDRX "\n", sprn, sprn, ctx->nip);
9fceefa7 3927 }
077fc206
JM
3928 printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3929 sprn, sprn, ctx->nip);
f24e5695 3930 }
e1833e1f 3931 GEN_EXCP_PRIVREG(ctx);
79aceca5 3932 }
3fc6c082
FB
3933 } else {
3934 /* Not defined */
4a057712 3935 if (loglevel != 0) {
077fc206
JM
3936 fprintf(logfile, "Trying to read invalid spr %d %03x at "
3937 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 3938 }
077fc206
JM
3939 printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3940 sprn, sprn, ctx->nip);
e1833e1f
JM
3941 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3942 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 3943 }
79aceca5
FB
3944}
3945
3fc6c082 3946GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
79aceca5 3947{
3fc6c082 3948 gen_op_mfspr(ctx);
76a66253 3949}
3fc6c082
FB
3950
3951/* mftb */
a750fc0b 3952GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3fc6c082
FB
3953{
3954 gen_op_mfspr(ctx);
79aceca5
FB
3955}
3956
3957/* mtcrf */
8dd4983c 3958GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
79aceca5 3959{
76a66253 3960 uint32_t crm, crn;
3b46e624 3961
76a66253
JM
3962 crm = CRM(ctx->opcode);
3963 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
a7812ae4 3964 TCGv_i32 temp = tcg_temp_new_i32();
76a66253 3965 crn = ffs(crm);
a7812ae4
PB
3966 tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
3967 tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
e1571908 3968 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
a7812ae4 3969 tcg_temp_free_i32(temp);
76a66253 3970 } else {
a7812ae4
PB
3971 TCGv_i32 temp = tcg_const_i32(crm);
3972 gen_helper_store_cr(cpu_gpr[rS(ctx->opcode)], temp);
3973 tcg_temp_free_i32(temp);
76a66253 3974 }
79aceca5
FB
3975}
3976
3977/* mtmsr */
426613db 3978#if defined(TARGET_PPC64)
be147d08 3979GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
426613db
JM
3980{
3981#if defined(CONFIG_USER_ONLY)
e1833e1f 3982 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3983#else
3984 if (unlikely(!ctx->supervisor)) {
e1833e1f 3985 GEN_EXCP_PRIVREG(ctx);
426613db
JM
3986 return;
3987 }
f78fb44e 3988 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
3989 if (ctx->opcode & 0x00010000) {
3990 /* Special form that does not need any synchronisation */
3991 gen_op_update_riee();
3992 } else {
056b05f8
JM
3993 /* XXX: we need to update nip before the store
3994 * if we enter power saving mode, we will exit the loop
3995 * directly from ppc_store_msr
3996 */
be147d08 3997 gen_update_nip(ctx, ctx->nip);
6676f424 3998 gen_op_store_msr();
be147d08
JM
3999 /* Must stop the translation as machine state (may have) changed */
4000 /* Note that mtmsr is not always defined as context-synchronizing */
056b05f8 4001 ctx->exception = POWERPC_EXCP_STOP;
be147d08 4002 }
426613db
JM
4003#endif
4004}
4005#endif
4006
79aceca5
FB
4007GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
4008{
9a64fbe4 4009#if defined(CONFIG_USER_ONLY)
e1833e1f 4010 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4011#else
76a66253 4012 if (unlikely(!ctx->supervisor)) {
e1833e1f 4013 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4014 return;
9a64fbe4 4015 }
f78fb44e 4016 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
be147d08
JM
4017 if (ctx->opcode & 0x00010000) {
4018 /* Special form that does not need any synchronisation */
4019 gen_op_update_riee();
4020 } else {
056b05f8
JM
4021 /* XXX: we need to update nip before the store
4022 * if we enter power saving mode, we will exit the loop
4023 * directly from ppc_store_msr
4024 */
be147d08 4025 gen_update_nip(ctx, ctx->nip);
d9bce9d9 4026#if defined(TARGET_PPC64)
be147d08 4027 if (!ctx->sf_mode)
6676f424 4028 gen_op_store_msr_32();
be147d08 4029 else
d9bce9d9 4030#endif
6676f424 4031 gen_op_store_msr();
be147d08
JM
4032 /* Must stop the translation as machine state (may have) changed */
4033 /* Note that mtmsrd is not always defined as context-synchronizing */
056b05f8 4034 ctx->exception = POWERPC_EXCP_STOP;
be147d08 4035 }
9a64fbe4 4036#endif
79aceca5
FB
4037}
4038
4039/* mtspr */
4040GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
4041{
3fc6c082 4042 void (*write_cb)(void *opaque, int sprn);
79aceca5
FB
4043 uint32_t sprn = SPR(ctx->opcode);
4044
3fc6c082 4045#if !defined(CONFIG_USER_ONLY)
be147d08
JM
4046 if (ctx->supervisor == 2)
4047 write_cb = ctx->spr_cb[sprn].hea_write;
7863667f 4048 else if (ctx->supervisor)
3fc6c082
FB
4049 write_cb = ctx->spr_cb[sprn].oea_write;
4050 else
9a64fbe4 4051#endif
3fc6c082 4052 write_cb = ctx->spr_cb[sprn].uea_write;
76a66253
JM
4053 if (likely(write_cb != NULL)) {
4054 if (likely(write_cb != SPR_NOACCESS)) {
f78fb44e 4055 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3fc6c082
FB
4056 (*write_cb)(ctx, sprn);
4057 } else {
4058 /* Privilege exception */
4a057712 4059 if (loglevel != 0) {
077fc206
JM
4060 fprintf(logfile, "Trying to write privileged spr %d %03x at "
4061 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 4062 }
077fc206
JM
4063 printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
4064 sprn, sprn, ctx->nip);
e1833e1f 4065 GEN_EXCP_PRIVREG(ctx);
76a66253 4066 }
3fc6c082
FB
4067 } else {
4068 /* Not defined */
4a057712 4069 if (loglevel != 0) {
077fc206
JM
4070 fprintf(logfile, "Trying to write invalid spr %d %03x at "
4071 ADDRX "\n", sprn, sprn, ctx->nip);
f24e5695 4072 }
077fc206
JM
4073 printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
4074 sprn, sprn, ctx->nip);
e1833e1f
JM
4075 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
4076 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
79aceca5 4077 }
79aceca5
FB
4078}
4079
4080/*** Cache management ***/
79aceca5 4081/* dcbf */
0db1b20e 4082GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
79aceca5 4083{
dac454af 4084 /* XXX: specification says this is treated as a load by the MMU */
a7812ae4 4085 TCGv t0 = tcg_temp_new();
a7859e89 4086 gen_set_access_type(ACCESS_CACHE);
fea0c503
AJ
4087 gen_addr_reg_index(t0, ctx);
4088 gen_qemu_ld8u(t0, t0, ctx->mem_idx);
4089 tcg_temp_free(t0);
79aceca5
FB
4090}
4091
4092/* dcbi (Supervisor only) */
9a64fbe4 4093GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
79aceca5 4094{
a541f297 4095#if defined(CONFIG_USER_ONLY)
e1833e1f 4096 GEN_EXCP_PRIVOPC(ctx);
a541f297 4097#else
b61f2753 4098 TCGv EA, val;
76a66253 4099 if (unlikely(!ctx->supervisor)) {
e1833e1f 4100 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4101 return;
9a64fbe4 4102 }
a7812ae4 4103 EA = tcg_temp_new();
a7859e89 4104 gen_set_access_type(ACCESS_CACHE);
b61f2753 4105 gen_addr_reg_index(EA, ctx);
a7812ae4 4106 val = tcg_temp_new();
76a66253 4107 /* XXX: specification says this should be treated as a store by the MMU */
b61f2753
AJ
4108 gen_qemu_ld8u(val, EA, ctx->mem_idx);
4109 gen_qemu_st8(val, EA, ctx->mem_idx);
4110 tcg_temp_free(val);
4111 tcg_temp_free(EA);
a541f297 4112#endif
79aceca5
FB
4113}
4114
4115/* dcdst */
9a64fbe4 4116GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
79aceca5 4117{
76a66253 4118 /* XXX: specification say this is treated as a load by the MMU */
a7812ae4 4119 TCGv t0 = tcg_temp_new();
a7859e89 4120 gen_set_access_type(ACCESS_CACHE);
fea0c503
AJ
4121 gen_addr_reg_index(t0, ctx);
4122 gen_qemu_ld8u(t0, t0, ctx->mem_idx);
4123 tcg_temp_free(t0);
79aceca5
FB
4124}
4125
4126/* dcbt */
0db1b20e 4127GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
79aceca5 4128{
0db1b20e 4129 /* interpreted as no-op */
76a66253
JM
4130 /* XXX: specification say this is treated as a load by the MMU
4131 * but does not generate any exception
4132 */
79aceca5
FB
4133}
4134
4135/* dcbtst */
0db1b20e 4136GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
79aceca5 4137{
0db1b20e 4138 /* interpreted as no-op */
76a66253
JM
4139 /* XXX: specification say this is treated as a load by the MMU
4140 * but does not generate any exception
4141 */
79aceca5
FB
4142}
4143
4144/* dcbz */
d63001d1 4145#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
7863667f
JM
4146static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
4147 /* 32 bytes cache line size */
d63001d1 4148 {
7863667f
JM
4149#define gen_op_dcbz_l32_le_raw gen_op_dcbz_l32_raw
4150#define gen_op_dcbz_l32_le_user gen_op_dcbz_l32_user
4151#define gen_op_dcbz_l32_le_kernel gen_op_dcbz_l32_kernel
4152#define gen_op_dcbz_l32_le_hypv gen_op_dcbz_l32_hypv
4153#define gen_op_dcbz_l32_le_64_raw gen_op_dcbz_l32_64_raw
4154#define gen_op_dcbz_l32_le_64_user gen_op_dcbz_l32_64_user
4155#define gen_op_dcbz_l32_le_64_kernel gen_op_dcbz_l32_64_kernel
4156#define gen_op_dcbz_l32_le_64_hypv gen_op_dcbz_l32_64_hypv
4157 GEN_MEM_FUNCS(dcbz_l32),
d63001d1 4158 },
7863667f 4159 /* 64 bytes cache line size */
d63001d1 4160 {
7863667f
JM
4161#define gen_op_dcbz_l64_le_raw gen_op_dcbz_l64_raw
4162#define gen_op_dcbz_l64_le_user gen_op_dcbz_l64_user
4163#define gen_op_dcbz_l64_le_kernel gen_op_dcbz_l64_kernel
4164#define gen_op_dcbz_l64_le_hypv gen_op_dcbz_l64_hypv
4165#define gen_op_dcbz_l64_le_64_raw gen_op_dcbz_l64_64_raw
4166#define gen_op_dcbz_l64_le_64_user gen_op_dcbz_l64_64_user
4167#define gen_op_dcbz_l64_le_64_kernel gen_op_dcbz_l64_64_kernel
4168#define gen_op_dcbz_l64_le_64_hypv gen_op_dcbz_l64_64_hypv
4169 GEN_MEM_FUNCS(dcbz_l64),
d63001d1 4170 },
7863667f 4171 /* 128 bytes cache line size */
d63001d1 4172 {
7863667f
JM
4173#define gen_op_dcbz_l128_le_raw gen_op_dcbz_l128_raw
4174#define gen_op_dcbz_l128_le_user gen_op_dcbz_l128_user
4175#define gen_op_dcbz_l128_le_kernel gen_op_dcbz_l128_kernel
4176#define gen_op_dcbz_l128_le_hypv gen_op_dcbz_l128_hypv
4177#define gen_op_dcbz_l128_le_64_raw gen_op_dcbz_l128_64_raw
4178#define gen_op_dcbz_l128_le_64_user gen_op_dcbz_l128_64_user
4179#define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
4180#define gen_op_dcbz_l128_le_64_hypv gen_op_dcbz_l128_64_hypv
4181 GEN_MEM_FUNCS(dcbz_l128),
d63001d1 4182 },
7863667f 4183 /* tunable cache line size */
d63001d1 4184 {
7863667f
JM
4185#define gen_op_dcbz_le_raw gen_op_dcbz_raw
4186#define gen_op_dcbz_le_user gen_op_dcbz_user
4187#define gen_op_dcbz_le_kernel gen_op_dcbz_kernel
4188#define gen_op_dcbz_le_hypv gen_op_dcbz_hypv
4189#define gen_op_dcbz_le_64_raw gen_op_dcbz_64_raw
4190#define gen_op_dcbz_le_64_user gen_op_dcbz_64_user
4191#define gen_op_dcbz_le_64_kernel gen_op_dcbz_64_kernel
4192#define gen_op_dcbz_le_64_hypv gen_op_dcbz_64_hypv
4193 GEN_MEM_FUNCS(dcbz),
d63001d1 4194 },
76a66253 4195};
9a64fbe4 4196
b068d6a7
JM
4197static always_inline void handler_dcbz (DisasContext *ctx,
4198 int dcache_line_size)
d63001d1
JM
4199{
4200 int n;
4201
4202 switch (dcache_line_size) {
4203 case 32:
4204 n = 0;
4205 break;
4206 case 64:
4207 n = 1;
4208 break;
4209 case 128:
4210 n = 2;
4211 break;
4212 default:
4213 n = 3;
4214 break;
4215 }
4216 op_dcbz(n);
4217}
4218
4219GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
79aceca5 4220{
e2be8d8d 4221 gen_addr_reg_index(cpu_T[0], ctx);
d63001d1
JM
4222 handler_dcbz(ctx, ctx->dcache_line_size);
4223 gen_op_check_reservation();
4224}
4225
c7697e1f 4226GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
d63001d1 4227{
e2be8d8d 4228 gen_addr_reg_index(cpu_T[0], ctx);
d63001d1
JM
4229 if (ctx->opcode & 0x00200000)
4230 handler_dcbz(ctx, ctx->dcache_line_size);
4231 else
4232 handler_dcbz(ctx, -1);
4b3686fa 4233 gen_op_check_reservation();
79aceca5
FB
4234}
4235
4236/* icbi */
36f69651 4237#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
7863667f
JM
4238#define gen_op_icbi_le_raw gen_op_icbi_raw
4239#define gen_op_icbi_le_user gen_op_icbi_user
4240#define gen_op_icbi_le_kernel gen_op_icbi_kernel
4241#define gen_op_icbi_le_hypv gen_op_icbi_hypv
4242#define gen_op_icbi_le_64_raw gen_op_icbi_64_raw
4243#define gen_op_icbi_le_64_user gen_op_icbi_64_user
4244#define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
4245#define gen_op_icbi_le_64_hypv gen_op_icbi_64_hypv
4246static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
4247 GEN_MEM_FUNCS(icbi),
36f69651 4248};
e1833e1f 4249
1b413d55 4250GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
79aceca5 4251{
30032c94
JM
4252 /* NIP cannot be restored if the memory exception comes from an helper */
4253 gen_update_nip(ctx, ctx->nip - 4);
e2be8d8d 4254 gen_addr_reg_index(cpu_T[0], ctx);
36f69651 4255 op_icbi();
79aceca5
FB
4256}
4257
4258/* Optional: */
4259/* dcba */
a750fc0b 4260GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
79aceca5 4261{
0db1b20e
JM
4262 /* interpreted as no-op */
4263 /* XXX: specification say this is treated as a store by the MMU
4264 * but does not generate any exception
4265 */
79aceca5
FB
4266}
4267
4268/*** Segment register manipulation ***/
4269/* Supervisor only: */
4270/* mfsr */
4271GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
4272{
9a64fbe4 4273#if defined(CONFIG_USER_ONLY)
e1833e1f 4274 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4275#else
76a66253 4276 if (unlikely(!ctx->supervisor)) {
e1833e1f 4277 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4278 return;
9a64fbe4 4279 }
86c581dc 4280 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
76a66253 4281 gen_op_load_sr();
f78fb44e 4282 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
9a64fbe4 4283#endif
79aceca5
FB
4284}
4285
4286/* mfsrin */
9a64fbe4 4287GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
79aceca5 4288{
9a64fbe4 4289#if defined(CONFIG_USER_ONLY)
e1833e1f 4290 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4291#else
76a66253 4292 if (unlikely(!ctx->supervisor)) {
e1833e1f 4293 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4294 return;
9a64fbe4 4295 }
f78fb44e 4296 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4297 gen_op_srli_T1(28);
4298 gen_op_load_sr();
f78fb44e 4299 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
9a64fbe4 4300#endif
79aceca5
FB
4301}
4302
4303/* mtsr */
e63c59cb 4304GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
79aceca5 4305{
9a64fbe4 4306#if defined(CONFIG_USER_ONLY)
e1833e1f 4307 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4308#else
76a66253 4309 if (unlikely(!ctx->supervisor)) {
e1833e1f 4310 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4311 return;
9a64fbe4 4312 }
f78fb44e 4313 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4314 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
76a66253 4315 gen_op_store_sr();
9a64fbe4 4316#endif
79aceca5
FB
4317}
4318
4319/* mtsrin */
9a64fbe4 4320GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
79aceca5 4321{
9a64fbe4 4322#if defined(CONFIG_USER_ONLY)
e1833e1f 4323 GEN_EXCP_PRIVREG(ctx);
9a64fbe4 4324#else
76a66253 4325 if (unlikely(!ctx->supervisor)) {
e1833e1f 4326 GEN_EXCP_PRIVREG(ctx);
9fddaa0c 4327 return;
9a64fbe4 4328 }
f78fb44e
AJ
4329 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4330 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4331 gen_op_srli_T1(28);
4332 gen_op_store_sr();
9a64fbe4 4333#endif
79aceca5
FB
4334}
4335
12de9a39
JM
4336#if defined(TARGET_PPC64)
4337/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
4338/* mfsr */
c7697e1f 4339GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
12de9a39
JM
4340{
4341#if defined(CONFIG_USER_ONLY)
4342 GEN_EXCP_PRIVREG(ctx);
4343#else
4344 if (unlikely(!ctx->supervisor)) {
4345 GEN_EXCP_PRIVREG(ctx);
4346 return;
4347 }
86c581dc 4348 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
12de9a39 4349 gen_op_load_slb();
f78fb44e 4350 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
12de9a39
JM
4351#endif
4352}
4353
4354/* mfsrin */
c7697e1f
JM
4355GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
4356 PPC_SEGMENT_64B)
12de9a39
JM
4357{
4358#if defined(CONFIG_USER_ONLY)
4359 GEN_EXCP_PRIVREG(ctx);
4360#else
4361 if (unlikely(!ctx->supervisor)) {
4362 GEN_EXCP_PRIVREG(ctx);
4363 return;
4364 }
f78fb44e 4365 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
12de9a39
JM
4366 gen_op_srli_T1(28);
4367 gen_op_load_slb();
f78fb44e 4368 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
12de9a39
JM
4369#endif
4370}
4371
4372/* mtsr */
c7697e1f 4373GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
12de9a39
JM
4374{
4375#if defined(CONFIG_USER_ONLY)
4376 GEN_EXCP_PRIVREG(ctx);
4377#else
4378 if (unlikely(!ctx->supervisor)) {
4379 GEN_EXCP_PRIVREG(ctx);
4380 return;
4381 }
f78fb44e 4382 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4383 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
12de9a39
JM
4384 gen_op_store_slb();
4385#endif
4386}
4387
4388/* mtsrin */
c7697e1f
JM
4389GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
4390 PPC_SEGMENT_64B)
12de9a39
JM
4391{
4392#if defined(CONFIG_USER_ONLY)
4393 GEN_EXCP_PRIVREG(ctx);
4394#else
4395 if (unlikely(!ctx->supervisor)) {
4396 GEN_EXCP_PRIVREG(ctx);
4397 return;
4398 }
f78fb44e
AJ
4399 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4400 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
12de9a39
JM
4401 gen_op_srli_T1(28);
4402 gen_op_store_slb();
4403#endif
4404}
4405#endif /* defined(TARGET_PPC64) */
4406
79aceca5
FB
4407/*** Lookaside buffer management ***/
4408/* Optional & supervisor only: */
4409/* tlbia */
3fc6c082 4410GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
79aceca5 4411{
9a64fbe4 4412#if defined(CONFIG_USER_ONLY)
e1833e1f 4413 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4414#else
76a66253 4415 if (unlikely(!ctx->supervisor)) {
e1833e1f 4416 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4417 return;
9a64fbe4
FB
4418 }
4419 gen_op_tlbia();
4420#endif
79aceca5
FB
4421}
4422
4423/* tlbie */
76a66253 4424GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
79aceca5 4425{
9a64fbe4 4426#if defined(CONFIG_USER_ONLY)
e1833e1f 4427 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4428#else
76a66253 4429 if (unlikely(!ctx->supervisor)) {
e1833e1f 4430 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4431 return;
9a64fbe4 4432 }
f78fb44e 4433 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
d9bce9d9
JM
4434#if defined(TARGET_PPC64)
4435 if (ctx->sf_mode)
4436 gen_op_tlbie_64();
4437 else
4438#endif
4439 gen_op_tlbie();
9a64fbe4 4440#endif
79aceca5
FB
4441}
4442
4443/* tlbsync */
76a66253 4444GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
79aceca5 4445{
9a64fbe4 4446#if defined(CONFIG_USER_ONLY)
e1833e1f 4447 GEN_EXCP_PRIVOPC(ctx);
9a64fbe4 4448#else
76a66253 4449 if (unlikely(!ctx->supervisor)) {
e1833e1f 4450 GEN_EXCP_PRIVOPC(ctx);
9fddaa0c 4451 return;
9a64fbe4
FB
4452 }
4453 /* This has no effect: it should ensure that all previous
4454 * tlbie have completed
4455 */
e1833e1f 4456 GEN_STOP(ctx);
9a64fbe4 4457#endif
79aceca5
FB
4458}
4459
426613db
JM
4460#if defined(TARGET_PPC64)
4461/* slbia */
4462GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
4463{
4464#if defined(CONFIG_USER_ONLY)
e1833e1f 4465 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4466#else
4467 if (unlikely(!ctx->supervisor)) {
e1833e1f 4468 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4469 return;
4470 }
4471 gen_op_slbia();
426613db
JM
4472#endif
4473}
4474
4475/* slbie */
4476GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
4477{
4478#if defined(CONFIG_USER_ONLY)
e1833e1f 4479 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4480#else
4481 if (unlikely(!ctx->supervisor)) {
e1833e1f 4482 GEN_EXCP_PRIVOPC(ctx);
426613db
JM
4483 return;
4484 }
f78fb44e 4485 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
426613db 4486 gen_op_slbie();
426613db
JM
4487#endif
4488}
4489#endif
4490
79aceca5
FB
4491/*** External control ***/
4492/* Optional: */
9a64fbe4
FB
4493#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
4494#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
7863667f
JM
4495static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
4496 GEN_MEM_FUNCS(eciwx),
111bfab3 4497};
7863667f
JM
4498static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
4499 GEN_MEM_FUNCS(ecowx),
111bfab3 4500};
9a64fbe4 4501
111bfab3 4502/* eciwx */
79aceca5
FB
4503GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
4504{
9a64fbe4 4505 /* Should check EAR[E] & alignment ! */
a7859e89 4506 gen_set_access_type(ACCESS_RES);
e2be8d8d 4507 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 4508 op_eciwx();
f78fb44e 4509 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
4510}
4511
4512/* ecowx */
4513GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
4514{
4515 /* Should check EAR[E] & alignment ! */
e2be8d8d 4516 gen_addr_reg_index(cpu_T[0], ctx);
f78fb44e 4517 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
4518 op_ecowx();
4519}
4520
4521/* PowerPC 601 specific instructions */
4522/* abs - abs. */
4523GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
4524{
f78fb44e 4525 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4526 gen_op_POWER_abs();
f78fb44e 4527 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4528 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4529 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4530}
4531
4532/* abso - abso. */
4533GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
4534{
f78fb44e 4535 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4536 gen_op_POWER_abso();
f78fb44e 4537 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4538 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4539 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4540}
4541
4542/* clcs */
a750fc0b 4543GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
76a66253 4544{
f78fb44e 4545 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4546 gen_op_POWER_clcs();
c7697e1f 4547 /* Rc=1 sets CR0 to an undefined state */
f78fb44e 4548 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
4549}
4550
4551/* div - div. */
4552GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
4553{
f78fb44e
AJ
4554 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4555 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4556 gen_op_POWER_div();
f78fb44e 4557 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4558 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4559 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4560}
4561
4562/* divo - divo. */
4563GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
4564{
f78fb44e
AJ
4565 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4566 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4567 gen_op_POWER_divo();
f78fb44e 4568 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4569 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4570 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4571}
4572
4573/* divs - divs. */
4574GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
4575{
f78fb44e
AJ
4576 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4577 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4578 gen_op_POWER_divs();
f78fb44e 4579 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4580 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4581 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4582}
4583
4584/* divso - divso. */
4585GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
4586{
f78fb44e
AJ
4587 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4588 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4589 gen_op_POWER_divso();
f78fb44e 4590 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4591 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4592 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4593}
4594
4595/* doz - doz. */
4596GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
4597{
f78fb44e
AJ
4598 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4599 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4600 gen_op_POWER_doz();
f78fb44e 4601 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4602 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4603 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4604}
4605
4606/* dozo - dozo. */
4607GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
4608{
f78fb44e
AJ
4609 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4610 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4611 gen_op_POWER_dozo();
f78fb44e 4612 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4613 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4614 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4615}
4616
4617/* dozi */
4618GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4619{
f78fb44e 4620 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
86c581dc 4621 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
76a66253 4622 gen_op_POWER_doz();
f78fb44e 4623 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
4624}
4625
7863667f
JM
4626/* As lscbx load from memory byte after byte, it's always endian safe.
4627 * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
4628 */
2857068e 4629#define op_POWER_lscbx(start, ra, rb) \
76a66253 4630(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
7863667f
JM
4631#define gen_op_POWER_lscbx_64_raw gen_op_POWER_lscbx_raw
4632#define gen_op_POWER_lscbx_64_user gen_op_POWER_lscbx_user
4633#define gen_op_POWER_lscbx_64_kernel gen_op_POWER_lscbx_kernel
4634#define gen_op_POWER_lscbx_64_hypv gen_op_POWER_lscbx_hypv
4635#define gen_op_POWER_lscbx_le_raw gen_op_POWER_lscbx_raw
4636#define gen_op_POWER_lscbx_le_user gen_op_POWER_lscbx_user
4637#define gen_op_POWER_lscbx_le_kernel gen_op_POWER_lscbx_kernel
4638#define gen_op_POWER_lscbx_le_hypv gen_op_POWER_lscbx_hypv
4639#define gen_op_POWER_lscbx_le_64_raw gen_op_POWER_lscbx_raw
4640#define gen_op_POWER_lscbx_le_64_user gen_op_POWER_lscbx_user
4641#define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
4642#define gen_op_POWER_lscbx_le_64_hypv gen_op_POWER_lscbx_hypv
4643static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
4644 GEN_MEM_FUNCS(POWER_lscbx),
76a66253 4645};
76a66253
JM
4646
4647/* lscbx - lscbx. */
4648GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4649{
4650 int ra = rA(ctx->opcode);
4651 int rb = rB(ctx->opcode);
4652
e2be8d8d 4653 gen_addr_reg_index(cpu_T[0], ctx);
76a66253
JM
4654 if (ra == 0) {
4655 ra = rb;
4656 }
4657 /* NIP cannot be restored if the memory exception comes from an helper */
d9bce9d9 4658 gen_update_nip(ctx, ctx->nip - 4);
3d7b417e
AJ
4659 tcg_gen_andi_tl(cpu_T[1], cpu_xer, 0x7F);
4660 tcg_gen_shri_tl(cpu_T[2], cpu_xer, XER_CMP);
4661 tcg_gen_andi_tl(cpu_T[2], cpu_T[2], 0xFF);
76a66253 4662 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
3d7b417e
AJ
4663 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
4664 tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
76a66253 4665 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4666 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4667}
4668
4669/* maskg - maskg. */
4670GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4671{
f78fb44e
AJ
4672 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4673 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4674 gen_op_POWER_maskg();
f78fb44e 4675 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4676 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4677 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4678}
4679
4680/* maskir - maskir. */
4681GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4682{
f78fb44e
AJ
4683 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4684 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4685 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
76a66253 4686 gen_op_POWER_maskir();
f78fb44e 4687 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4688 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4689 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4690}
4691
4692/* mul - mul. */
4693GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4694{
f78fb44e
AJ
4695 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4696 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4697 gen_op_POWER_mul();
f78fb44e 4698 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4699 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4700 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4701}
4702
4703/* mulo - mulo. */
4704GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4705{
f78fb44e
AJ
4706 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4707 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4708 gen_op_POWER_mulo();
f78fb44e 4709 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4710 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4711 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4712}
4713
4714/* nabs - nabs. */
4715GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4716{
f78fb44e 4717 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4718 gen_op_POWER_nabs();
f78fb44e 4719 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4720 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4721 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4722}
4723
4724/* nabso - nabso. */
4725GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4726{
f78fb44e 4727 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 4728 gen_op_POWER_nabso();
f78fb44e 4729 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 4730 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4731 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4732}
4733
4734/* rlmi - rlmi. */
4735GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4736{
4737 uint32_t mb, me;
4738
4739 mb = MB(ctx->opcode);
4740 me = ME(ctx->opcode);
f78fb44e
AJ
4741 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4742 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4743 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
76a66253 4744 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
f78fb44e 4745 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4746 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4747 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4748}
4749
4750/* rrib - rrib. */
4751GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4752{
f78fb44e
AJ
4753 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4754 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4755 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
76a66253 4756 gen_op_POWER_rrib();
f78fb44e 4757 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4758 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4759 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4760}
4761
4762/* sle - sle. */
4763GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4764{
f78fb44e
AJ
4765 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4766 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4767 gen_op_POWER_sle();
f78fb44e 4768 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4769 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4770 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4771}
4772
4773/* sleq - sleq. */
4774GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4775{
f78fb44e
AJ
4776 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4777 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4778 gen_op_POWER_sleq();
f78fb44e 4779 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4780 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4781 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4782}
4783
4784/* sliq - sliq. */
4785GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4786{
f78fb44e 4787 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4788 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
76a66253 4789 gen_op_POWER_sle();
f78fb44e 4790 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4791 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4792 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4793}
4794
4795/* slliq - slliq. */
4796GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4797{
f78fb44e 4798 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4799 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
76a66253 4800 gen_op_POWER_sleq();
f78fb44e 4801 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4802 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4803 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4804}
4805
4806/* sllq - sllq. */
4807GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4808{
f78fb44e
AJ
4809 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4810 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4811 gen_op_POWER_sllq();
f78fb44e 4812 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4813 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4814 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4815}
4816
4817/* slq - slq. */
4818GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4819{
f78fb44e
AJ
4820 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4821 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4822 gen_op_POWER_slq();
f78fb44e 4823 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4824 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4825 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4826}
4827
d9bce9d9 4828/* sraiq - sraiq. */
76a66253
JM
4829GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4830{
f78fb44e 4831 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4832 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
76a66253 4833 gen_op_POWER_sraq();
f78fb44e 4834 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4835 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4836 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4837}
4838
4839/* sraq - sraq. */
4840GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4841{
f78fb44e
AJ
4842 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4843 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4844 gen_op_POWER_sraq();
f78fb44e 4845 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4846 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4847 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4848}
4849
4850/* sre - sre. */
4851GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4852{
f78fb44e
AJ
4853 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4854 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4855 gen_op_POWER_sre();
f78fb44e 4856 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4857 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4858 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4859}
4860
4861/* srea - srea. */
4862GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4863{
f78fb44e
AJ
4864 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4865 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4866 gen_op_POWER_srea();
f78fb44e 4867 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4868 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4869 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4870}
4871
4872/* sreq */
4873GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4874{
f78fb44e
AJ
4875 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4876 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4877 gen_op_POWER_sreq();
f78fb44e 4878 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4879 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4880 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4881}
4882
4883/* sriq */
4884GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4885{
f78fb44e 4886 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
86c581dc 4887 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
76a66253 4888 gen_op_POWER_srq();
f78fb44e 4889 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4890 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4891 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4892}
4893
4894/* srliq */
4895GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4896{
f78fb44e
AJ
4897 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4898 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
86c581dc 4899 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
76a66253 4900 gen_op_POWER_srlq();
f78fb44e 4901 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4902 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4903 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4904}
4905
4906/* srlq */
4907GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
4908{
f78fb44e
AJ
4909 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4910 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4911 gen_op_POWER_srlq();
f78fb44e 4912 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4913 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4914 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4915}
4916
4917/* srq */
4918GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
4919{
f78fb44e
AJ
4920 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4921 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 4922 gen_op_POWER_srq();
f78fb44e 4923 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
76a66253 4924 if (unlikely(Rc(ctx->opcode) != 0))
e1571908 4925 gen_set_Rc0(ctx, cpu_T[0]);
76a66253
JM
4926}
4927
4928/* PowerPC 602 specific instructions */
4929/* dsa */
4930GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
4931{
4932 /* XXX: TODO */
e1833e1f 4933 GEN_EXCP_INVAL(ctx);
76a66253
JM
4934}
4935
4936/* esa */
4937GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
4938{
4939 /* XXX: TODO */
e1833e1f 4940 GEN_EXCP_INVAL(ctx);
76a66253
JM
4941}
4942
4943/* mfrom */
4944GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4945{
4946#if defined(CONFIG_USER_ONLY)
e1833e1f 4947 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4948#else
4949 if (unlikely(!ctx->supervisor)) {
e1833e1f 4950 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4951 return;
4952 }
cf02a65c 4953 gen_helper_602_mfrom(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
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 }
0f3955e2 4968 gen_helper_load_6xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4969#endif
4970}
4971
4972/* tlbli */
c7697e1f 4973GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
76a66253
JM
4974{
4975#if defined(CONFIG_USER_ONLY)
e1833e1f 4976 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4977#else
4978 if (unlikely(!ctx->supervisor)) {
e1833e1f 4979 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
4980 return;
4981 }
0f3955e2 4982 gen_helper_load_6xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
76a66253
JM
4983#endif
4984}
4985
7dbe11ac
JM
4986/* 74xx TLB management */
4987/* tlbld */
c7697e1f 4988GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
4989{
4990#if defined(CONFIG_USER_ONLY)
4991 GEN_EXCP_PRIVOPC(ctx);
4992#else
4993 if (unlikely(!ctx->supervisor)) {
4994 GEN_EXCP_PRIVOPC(ctx);
4995 return;
4996 }
0f3955e2 4997 gen_helper_load_74xx_tlbd(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
4998#endif
4999}
5000
5001/* tlbli */
c7697e1f 5002GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
7dbe11ac
JM
5003{
5004#if defined(CONFIG_USER_ONLY)
5005 GEN_EXCP_PRIVOPC(ctx);
5006#else
5007 if (unlikely(!ctx->supervisor)) {
5008 GEN_EXCP_PRIVOPC(ctx);
5009 return;
5010 }
0f3955e2 5011 gen_helper_load_74xx_tlbi(cpu_gpr[rB(ctx->opcode)]);
7dbe11ac
JM
5012#endif
5013}
5014
76a66253
JM
5015/* POWER instructions not in PowerPC 601 */
5016/* clf */
5017GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
5018{
5019 /* Cache line flush: implemented as no-op */
5020}
5021
5022/* cli */
5023GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
5024{
7f75ffd3 5025 /* Cache line invalidate: privileged and treated as no-op */
76a66253 5026#if defined(CONFIG_USER_ONLY)
e1833e1f 5027 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5028#else
5029 if (unlikely(!ctx->supervisor)) {
e1833e1f 5030 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5031 return;
5032 }
5033#endif
5034}
5035
5036/* dclst */
5037GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
5038{
5039 /* Data cache line store: treated as no-op */
5040}
5041
5042GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
5043{
5044#if defined(CONFIG_USER_ONLY)
e1833e1f 5045 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5046#else
5047 if (unlikely(!ctx->supervisor)) {
e1833e1f 5048 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5049 return;
5050 }
5051 int ra = rA(ctx->opcode);
5052 int rd = rD(ctx->opcode);
5053
e2be8d8d 5054 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5055 gen_op_POWER_mfsri();
f78fb44e 5056 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
76a66253 5057 if (ra != 0 && ra != rd)
f78fb44e 5058 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
76a66253
JM
5059#endif
5060}
5061
5062GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
5063{
5064#if defined(CONFIG_USER_ONLY)
e1833e1f 5065 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5066#else
5067 if (unlikely(!ctx->supervisor)) {
e1833e1f 5068 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5069 return;
5070 }
e2be8d8d 5071 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5072 gen_op_POWER_rac();
f78fb44e 5073 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5074#endif
5075}
5076
5077GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
5078{
5079#if defined(CONFIG_USER_ONLY)
e1833e1f 5080 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5081#else
5082 if (unlikely(!ctx->supervisor)) {
e1833e1f 5083 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5084 return;
5085 }
5086 gen_op_POWER_rfsvc();
e1833e1f 5087 GEN_SYNC(ctx);
76a66253
JM
5088#endif
5089}
5090
5091/* svc is not implemented for now */
5092
5093/* POWER2 specific instructions */
5094/* Quad manipulation (load/store two floats at a time) */
76a66253
JM
5095
5096/* lfq */
5097GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5098{
01a4afeb
AJ
5099 int rd = rD(ctx->opcode);
5100 TCGv t0 = tcg_temp_new();
5101 gen_addr_imm_index(t0, ctx, 0);
5102 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5103 tcg_gen_addi_tl(t0, t0, 8);
5104 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5105 tcg_temp_free(t0);
76a66253
JM
5106}
5107
5108/* lfqu */
5109GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5110{
5111 int ra = rA(ctx->opcode);
01a4afeb
AJ
5112 int rd = rD(ctx->opcode);
5113 TCGv t0 = tcg_temp_new();
5114 TCGv t1 = tcg_temp_new();
5115 gen_addr_imm_index(t0, ctx, 0);
5116 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5117 tcg_gen_addi_tl(t1, t0, 8);
5118 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5119 if (ra != 0)
01a4afeb
AJ
5120 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5121 tcg_temp_free(t0);
5122 tcg_temp_free(t1);
76a66253
JM
5123}
5124
5125/* lfqux */
5126GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
5127{
5128 int ra = rA(ctx->opcode);
01a4afeb
AJ
5129 int rd = rD(ctx->opcode);
5130 TCGv t0 = tcg_temp_new();
5131 TCGv t1 = tcg_temp_new();
5132 gen_addr_reg_index(t0, ctx);
5133 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5134 tcg_gen_addi_tl(t1, t0, 8);
5135 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5136 if (ra != 0)
01a4afeb
AJ
5137 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5138 tcg_temp_free(t0);
5139 tcg_temp_free(t1);
76a66253
JM
5140}
5141
5142/* lfqx */
5143GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
5144{
01a4afeb
AJ
5145 int rd = rD(ctx->opcode);
5146 TCGv t0 = tcg_temp_new();
5147 gen_addr_reg_index(t0, ctx);
5148 gen_qemu_ld64(cpu_fpr[rd], t0, ctx->mem_idx);
5149 tcg_gen_addi_tl(t0, t0, 8);
5150 gen_qemu_ld64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5151 tcg_temp_free(t0);
76a66253
JM
5152}
5153
5154/* stfq */
5155GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5156{
01a4afeb
AJ
5157 int rd = rD(ctx->opcode);
5158 TCGv t0 = tcg_temp_new();
5159 gen_addr_imm_index(t0, ctx, 0);
5160 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5161 tcg_gen_addi_tl(t0, t0, 8);
5162 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5163 tcg_temp_free(t0);
76a66253
JM
5164}
5165
5166/* stfqu */
5167GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
5168{
5169 int ra = rA(ctx->opcode);
01a4afeb
AJ
5170 int rd = rD(ctx->opcode);
5171 TCGv t0 = tcg_temp_new();
5172 TCGv t1 = tcg_temp_new();
5173 gen_addr_imm_index(t0, ctx, 0);
5174 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5175 tcg_gen_addi_tl(t1, t0, 8);
5176 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5177 if (ra != 0)
01a4afeb
AJ
5178 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5179 tcg_temp_free(t0);
5180 tcg_temp_free(t1);
76a66253
JM
5181}
5182
5183/* stfqux */
5184GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
5185{
5186 int ra = rA(ctx->opcode);
01a4afeb
AJ
5187 int rd = rD(ctx->opcode);
5188 TCGv t0 = tcg_temp_new();
5189 TCGv t1 = tcg_temp_new();
5190 gen_addr_reg_index(t0, ctx);
5191 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5192 tcg_gen_addi_tl(t1, t0, 8);
5193 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t1, ctx->mem_idx);
76a66253 5194 if (ra != 0)
01a4afeb
AJ
5195 tcg_gen_mov_tl(cpu_gpr[ra], t0);
5196 tcg_temp_free(t0);
5197 tcg_temp_free(t1);
76a66253
JM
5198}
5199
5200/* stfqx */
5201GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
5202{
01a4afeb
AJ
5203 int rd = rD(ctx->opcode);
5204 TCGv t0 = tcg_temp_new();
5205 gen_addr_reg_index(t0, ctx);
5206 gen_qemu_st64(cpu_fpr[rd], t0, ctx->mem_idx);
5207 tcg_gen_addi_tl(t0, t0, 8);
5208 gen_qemu_st64(cpu_fpr[(rd + 1) % 32], t0, ctx->mem_idx);
5209 tcg_temp_free(t0);
76a66253
JM
5210}
5211
5212/* BookE specific instructions */
2662a059 5213/* XXX: not implemented on 440 ? */
05332d70 5214GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
76a66253
JM
5215{
5216 /* XXX: TODO */
e1833e1f 5217 GEN_EXCP_INVAL(ctx);
76a66253
JM
5218}
5219
2662a059 5220/* XXX: not implemented on 440 ? */
05332d70 5221GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
76a66253
JM
5222{
5223#if defined(CONFIG_USER_ONLY)
e1833e1f 5224 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5225#else
5226 if (unlikely(!ctx->supervisor)) {
e1833e1f 5227 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5228 return;
5229 }
e2be8d8d 5230 gen_addr_reg_index(cpu_T[0], ctx);
76a66253 5231 /* Use the same micro-ops as for tlbie */
d9bce9d9
JM
5232#if defined(TARGET_PPC64)
5233 if (ctx->sf_mode)
5234 gen_op_tlbie_64();
5235 else
5236#endif
5237 gen_op_tlbie();
76a66253
JM
5238#endif
5239}
5240
5241/* All 405 MAC instructions are translated here */
b068d6a7
JM
5242static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
5243 int opc2, int opc3,
5244 int ra, int rb, int rt, int Rc)
76a66253 5245{
182608d4
AJ
5246 TCGv t0, t1;
5247
a7812ae4
PB
5248 t0 = tcg_temp_local_new();
5249 t1 = tcg_temp_local_new();
182608d4 5250
76a66253
JM
5251 switch (opc3 & 0x0D) {
5252 case 0x05:
5253 /* macchw - macchw. - macchwo - macchwo. */
5254 /* macchws - macchws. - macchwso - macchwso. */
5255 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
5256 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
5257 /* mulchw - mulchw. */
182608d4
AJ
5258 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5259 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5260 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5261 break;
5262 case 0x04:
5263 /* macchwu - macchwu. - macchwuo - macchwuo. */
5264 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
5265 /* mulchwu - mulchwu. */
182608d4
AJ
5266 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5267 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5268 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5269 break;
5270 case 0x01:
5271 /* machhw - machhw. - machhwo - machhwo. */
5272 /* machhws - machhws. - machhwso - machhwso. */
5273 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
5274 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
5275 /* mulhhw - mulhhw. */
182608d4
AJ
5276 tcg_gen_sari_tl(t0, cpu_gpr[ra], 16);
5277 tcg_gen_ext16s_tl(t0, t0);
5278 tcg_gen_sari_tl(t1, cpu_gpr[rb], 16);
5279 tcg_gen_ext16s_tl(t1, t1);
76a66253
JM
5280 break;
5281 case 0x00:
5282 /* machhwu - machhwu. - machhwuo - machhwuo. */
5283 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
5284 /* mulhhwu - mulhhwu. */
182608d4
AJ
5285 tcg_gen_shri_tl(t0, cpu_gpr[ra], 16);
5286 tcg_gen_ext16u_tl(t0, t0);
5287 tcg_gen_shri_tl(t1, cpu_gpr[rb], 16);
5288 tcg_gen_ext16u_tl(t1, t1);
76a66253
JM
5289 break;
5290 case 0x0D:
5291 /* maclhw - maclhw. - maclhwo - maclhwo. */
5292 /* maclhws - maclhws. - maclhwso - maclhwso. */
5293 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
5294 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
5295 /* mullhw - mullhw. */
182608d4
AJ
5296 tcg_gen_ext16s_tl(t0, cpu_gpr[ra]);
5297 tcg_gen_ext16s_tl(t1, cpu_gpr[rb]);
76a66253
JM
5298 break;
5299 case 0x0C:
5300 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
5301 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
5302 /* mullhwu - mullhwu. */
182608d4
AJ
5303 tcg_gen_ext16u_tl(t0, cpu_gpr[ra]);
5304 tcg_gen_ext16u_tl(t1, cpu_gpr[rb]);
76a66253
JM
5305 break;
5306 }
76a66253 5307 if (opc2 & 0x04) {
182608d4
AJ
5308 /* (n)multiply-and-accumulate (0x0C / 0x0E) */
5309 tcg_gen_mul_tl(t1, t0, t1);
5310 if (opc2 & 0x02) {
5311 /* nmultiply-and-accumulate (0x0E) */
5312 tcg_gen_sub_tl(t0, cpu_gpr[rt], t1);
5313 } else {
5314 /* multiply-and-accumulate (0x0C) */
5315 tcg_gen_add_tl(t0, cpu_gpr[rt], t1);
5316 }
5317
5318 if (opc3 & 0x12) {
5319 /* Check overflow and/or saturate */
5320 int l1 = gen_new_label();
5321
5322 if (opc3 & 0x10) {
5323 /* Start with XER OV disabled, the most likely case */
5324 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_OV));
5325 }
5326 if (opc3 & 0x01) {
5327 /* Signed */
5328 tcg_gen_xor_tl(t1, cpu_gpr[rt], t1);
5329 tcg_gen_brcondi_tl(TCG_COND_GE, t1, 0, l1);
5330 tcg_gen_xor_tl(t1, cpu_gpr[rt], t0);
5331 tcg_gen_brcondi_tl(TCG_COND_LT, t1, 0, l1);
bdc4e053 5332 if (opc3 & 0x02) {
182608d4
AJ
5333 /* Saturate */
5334 tcg_gen_sari_tl(t0, cpu_gpr[rt], 31);
5335 tcg_gen_xori_tl(t0, t0, 0x7fffffff);
5336 }
5337 } else {
5338 /* Unsigned */
5339 tcg_gen_brcond_tl(TCG_COND_GEU, t0, t1, l1);
bdc4e053 5340 if (opc3 & 0x02) {
182608d4
AJ
5341 /* Saturate */
5342 tcg_gen_movi_tl(t0, UINT32_MAX);
5343 }
5344 }
5345 if (opc3 & 0x10) {
5346 /* Check overflow */
5347 tcg_gen_ori_tl(cpu_xer, cpu_xer, (1 << XER_OV) | (1 << XER_SO));
5348 }
5349 gen_set_label(l1);
5350 tcg_gen_mov_tl(cpu_gpr[rt], t0);
5351 }
5352 } else {
5353 tcg_gen_mul_tl(cpu_gpr[rt], t0, t1);
76a66253 5354 }
182608d4
AJ
5355 tcg_temp_free(t0);
5356 tcg_temp_free(t1);
76a66253
JM
5357 if (unlikely(Rc) != 0) {
5358 /* Update Rc0 */
182608d4 5359 gen_set_Rc0(ctx, cpu_gpr[rt]);
76a66253
JM
5360 }
5361}
5362
a750fc0b
JM
5363#define GEN_MAC_HANDLER(name, opc2, opc3) \
5364GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
76a66253
JM
5365{ \
5366 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
5367 rD(ctx->opcode), Rc(ctx->opcode)); \
5368}
5369
5370/* macchw - macchw. */
a750fc0b 5371GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
76a66253 5372/* macchwo - macchwo. */
a750fc0b 5373GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
76a66253 5374/* macchws - macchws. */
a750fc0b 5375GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
76a66253 5376/* macchwso - macchwso. */
a750fc0b 5377GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
76a66253 5378/* macchwsu - macchwsu. */
a750fc0b 5379GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
76a66253 5380/* macchwsuo - macchwsuo. */
a750fc0b 5381GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
76a66253 5382/* macchwu - macchwu. */
a750fc0b 5383GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
76a66253 5384/* macchwuo - macchwuo. */
a750fc0b 5385GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
76a66253 5386/* machhw - machhw. */
a750fc0b 5387GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
76a66253 5388/* machhwo - machhwo. */
a750fc0b 5389GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
76a66253 5390/* machhws - machhws. */
a750fc0b 5391GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
76a66253 5392/* machhwso - machhwso. */
a750fc0b 5393GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
76a66253 5394/* machhwsu - machhwsu. */
a750fc0b 5395GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
76a66253 5396/* machhwsuo - machhwsuo. */
a750fc0b 5397GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
76a66253 5398/* machhwu - machhwu. */
a750fc0b 5399GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
76a66253 5400/* machhwuo - machhwuo. */
a750fc0b 5401GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
76a66253 5402/* maclhw - maclhw. */
a750fc0b 5403GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
76a66253 5404/* maclhwo - maclhwo. */
a750fc0b 5405GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
76a66253 5406/* maclhws - maclhws. */
a750fc0b 5407GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
76a66253 5408/* maclhwso - maclhwso. */
a750fc0b 5409GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
76a66253 5410/* maclhwu - maclhwu. */
a750fc0b 5411GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
76a66253 5412/* maclhwuo - maclhwuo. */
a750fc0b 5413GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
76a66253 5414/* maclhwsu - maclhwsu. */
a750fc0b 5415GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
76a66253 5416/* maclhwsuo - maclhwsuo. */
a750fc0b 5417GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
76a66253 5418/* nmacchw - nmacchw. */
a750fc0b 5419GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
76a66253 5420/* nmacchwo - nmacchwo. */
a750fc0b 5421GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
76a66253 5422/* nmacchws - nmacchws. */
a750fc0b 5423GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
76a66253 5424/* nmacchwso - nmacchwso. */
a750fc0b 5425GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
76a66253 5426/* nmachhw - nmachhw. */
a750fc0b 5427GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
76a66253 5428/* nmachhwo - nmachhwo. */
a750fc0b 5429GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
76a66253 5430/* nmachhws - nmachhws. */
a750fc0b 5431GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
76a66253 5432/* nmachhwso - nmachhwso. */
a750fc0b 5433GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
76a66253 5434/* nmaclhw - nmaclhw. */
a750fc0b 5435GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
76a66253 5436/* nmaclhwo - nmaclhwo. */
a750fc0b 5437GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
76a66253 5438/* nmaclhws - nmaclhws. */
a750fc0b 5439GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
76a66253 5440/* nmaclhwso - nmaclhwso. */
a750fc0b 5441GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
76a66253
JM
5442
5443/* mulchw - mulchw. */
a750fc0b 5444GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
76a66253 5445/* mulchwu - mulchwu. */
a750fc0b 5446GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
76a66253 5447/* mulhhw - mulhhw. */
a750fc0b 5448GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
76a66253 5449/* mulhhwu - mulhhwu. */
a750fc0b 5450GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
76a66253 5451/* mullhw - mullhw. */
a750fc0b 5452GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
76a66253 5453/* mullhwu - mullhwu. */
a750fc0b 5454GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
76a66253
JM
5455
5456/* mfdcr */
05332d70 5457GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
76a66253
JM
5458{
5459#if defined(CONFIG_USER_ONLY)
e1833e1f 5460 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5461#else
5462 uint32_t dcrn = SPR(ctx->opcode);
5463
5464 if (unlikely(!ctx->supervisor)) {
e1833e1f 5465 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5466 return;
5467 }
86c581dc 5468 tcg_gen_movi_tl(cpu_T[0], dcrn);
a42bd6cc 5469 gen_op_load_dcr();
f78fb44e 5470 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5471#endif
5472}
5473
5474/* mtdcr */
05332d70 5475GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
76a66253
JM
5476{
5477#if defined(CONFIG_USER_ONLY)
e1833e1f 5478 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5479#else
5480 uint32_t dcrn = SPR(ctx->opcode);
5481
5482 if (unlikely(!ctx->supervisor)) {
e1833e1f 5483 GEN_EXCP_PRIVREG(ctx);
76a66253
JM
5484 return;
5485 }
86c581dc 5486 tcg_gen_movi_tl(cpu_T[0], dcrn);
f78fb44e 5487 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a42bd6cc
JM
5488 gen_op_store_dcr();
5489#endif
5490}
5491
5492/* mfdcrx */
2662a059 5493/* XXX: not implemented on 440 ? */
05332d70 5494GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5495{
5496#if defined(CONFIG_USER_ONLY)
e1833e1f 5497 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5498#else
5499 if (unlikely(!ctx->supervisor)) {
e1833e1f 5500 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5501 return;
5502 }
f78fb44e 5503 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a42bd6cc 5504 gen_op_load_dcr();
f78fb44e 5505 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
a750fc0b 5506 /* Note: Rc update flag set leads to undefined state of Rc0 */
a42bd6cc
JM
5507#endif
5508}
5509
5510/* mtdcrx */
2662a059 5511/* XXX: not implemented on 440 ? */
05332d70 5512GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
a42bd6cc
JM
5513{
5514#if defined(CONFIG_USER_ONLY)
e1833e1f 5515 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5516#else
5517 if (unlikely(!ctx->supervisor)) {
e1833e1f 5518 GEN_EXCP_PRIVREG(ctx);
a42bd6cc
JM
5519 return;
5520 }
f78fb44e
AJ
5521 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5522 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a42bd6cc 5523 gen_op_store_dcr();
a750fc0b 5524 /* Note: Rc update flag set leads to undefined state of Rc0 */
76a66253
JM
5525#endif
5526}
5527
a750fc0b
JM
5528/* mfdcrux (PPC 460) : user-mode access to DCR */
5529GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
5530{
f78fb44e 5531 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a750fc0b 5532 gen_op_load_dcr();
f78fb44e 5533 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
a750fc0b
JM
5534 /* Note: Rc update flag set leads to undefined state of Rc0 */
5535}
5536
5537/* mtdcrux (PPC 460) : user-mode access to DCR */
5538GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
5539{
f78fb44e
AJ
5540 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5541 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a750fc0b
JM
5542 gen_op_store_dcr();
5543 /* Note: Rc update flag set leads to undefined state of Rc0 */
5544}
5545
76a66253
JM
5546/* dccci */
5547GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
5548{
5549#if defined(CONFIG_USER_ONLY)
e1833e1f 5550 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5551#else
5552 if (unlikely(!ctx->supervisor)) {
e1833e1f 5553 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5554 return;
5555 }
5556 /* interpreted as no-op */
5557#endif
5558}
5559
5560/* dcread */
5561GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
5562{
5563#if defined(CONFIG_USER_ONLY)
e1833e1f 5564 GEN_EXCP_PRIVOPC(ctx);
76a66253 5565#else
b61f2753 5566 TCGv EA, val;
76a66253 5567 if (unlikely(!ctx->supervisor)) {
e1833e1f 5568 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5569 return;
5570 }
a7812ae4 5571 EA = tcg_temp_new();
a7859e89 5572 gen_set_access_type(ACCESS_CACHE);
b61f2753 5573 gen_addr_reg_index(EA, ctx);
a7812ae4 5574 val = tcg_temp_new();
b61f2753
AJ
5575 gen_qemu_ld32u(val, EA, ctx->mem_idx);
5576 tcg_temp_free(val);
5577 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], EA);
5578 tcg_temp_free(EA);
76a66253
JM
5579#endif
5580}
5581
5582/* icbt */
c7697e1f 5583GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
76a66253
JM
5584{
5585 /* interpreted as no-op */
5586 /* XXX: specification say this is treated as a load by the MMU
5587 * but does not generate any exception
5588 */
5589}
5590
5591/* iccci */
5592GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
5593{
5594#if defined(CONFIG_USER_ONLY)
e1833e1f 5595 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5596#else
5597 if (unlikely(!ctx->supervisor)) {
e1833e1f 5598 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5599 return;
5600 }
5601 /* interpreted as no-op */
5602#endif
5603}
5604
5605/* icread */
5606GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
5607{
5608#if defined(CONFIG_USER_ONLY)
e1833e1f 5609 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5610#else
5611 if (unlikely(!ctx->supervisor)) {
e1833e1f 5612 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5613 return;
5614 }
5615 /* interpreted as no-op */
5616#endif
5617}
5618
5619/* rfci (supervisor only) */
c7697e1f 5620GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
a42bd6cc
JM
5621{
5622#if defined(CONFIG_USER_ONLY)
e1833e1f 5623 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5624#else
5625 if (unlikely(!ctx->supervisor)) {
e1833e1f 5626 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5627 return;
5628 }
5629 /* Restore CPU state */
5630 gen_op_40x_rfci();
e1833e1f 5631 GEN_SYNC(ctx);
a42bd6cc
JM
5632#endif
5633}
5634
5635GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
5636{
5637#if defined(CONFIG_USER_ONLY)
e1833e1f 5638 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5639#else
5640 if (unlikely(!ctx->supervisor)) {
e1833e1f 5641 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5642 return;
5643 }
5644 /* Restore CPU state */
5645 gen_op_rfci();
e1833e1f 5646 GEN_SYNC(ctx);
a42bd6cc
JM
5647#endif
5648}
5649
5650/* BookE specific */
2662a059 5651/* XXX: not implemented on 440 ? */
05332d70 5652GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
76a66253
JM
5653{
5654#if defined(CONFIG_USER_ONLY)
e1833e1f 5655 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5656#else
5657 if (unlikely(!ctx->supervisor)) {
e1833e1f 5658 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5659 return;
5660 }
5661 /* Restore CPU state */
a42bd6cc 5662 gen_op_rfdi();
e1833e1f 5663 GEN_SYNC(ctx);
76a66253
JM
5664#endif
5665}
5666
2662a059 5667/* XXX: not implemented on 440 ? */
a750fc0b 5668GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
a42bd6cc
JM
5669{
5670#if defined(CONFIG_USER_ONLY)
e1833e1f 5671 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5672#else
5673 if (unlikely(!ctx->supervisor)) {
e1833e1f 5674 GEN_EXCP_PRIVOPC(ctx);
a42bd6cc
JM
5675 return;
5676 }
5677 /* Restore CPU state */
5678 gen_op_rfmci();
e1833e1f 5679 GEN_SYNC(ctx);
a42bd6cc
JM
5680#endif
5681}
5eb7995e 5682
d9bce9d9 5683/* TLB management - PowerPC 405 implementation */
76a66253 5684/* tlbre */
c7697e1f 5685GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
76a66253
JM
5686{
5687#if defined(CONFIG_USER_ONLY)
e1833e1f 5688 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5689#else
5690 if (unlikely(!ctx->supervisor)) {
e1833e1f 5691 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5692 return;
5693 }
5694 switch (rB(ctx->opcode)) {
5695 case 0:
f78fb44e 5696 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5697 gen_op_4xx_tlbre_hi();
f78fb44e 5698 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5699 break;
5700 case 1:
f78fb44e 5701 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
76a66253 5702 gen_op_4xx_tlbre_lo();
f78fb44e 5703 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253
JM
5704 break;
5705 default:
e1833e1f 5706 GEN_EXCP_INVAL(ctx);
76a66253 5707 break;
9a64fbe4 5708 }
76a66253
JM
5709#endif
5710}
5711
d9bce9d9 5712/* tlbsx - tlbsx. */
c7697e1f 5713GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
76a66253
JM
5714{
5715#if defined(CONFIG_USER_ONLY)
e1833e1f 5716 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5717#else
5718 if (unlikely(!ctx->supervisor)) {
e1833e1f 5719 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5720 return;
5721 }
e2be8d8d 5722 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5723 gen_op_4xx_tlbsx();
76a66253 5724 if (Rc(ctx->opcode))
daf4f96e 5725 gen_op_4xx_tlbsx_check();
f78fb44e 5726 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
76a66253 5727#endif
79aceca5
FB
5728}
5729
76a66253 5730/* tlbwe */
c7697e1f 5731GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
79aceca5 5732{
76a66253 5733#if defined(CONFIG_USER_ONLY)
e1833e1f 5734 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5735#else
5736 if (unlikely(!ctx->supervisor)) {
e1833e1f 5737 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5738 return;
5739 }
5740 switch (rB(ctx->opcode)) {
5741 case 0:
f78fb44e
AJ
5742 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5743 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5744 gen_op_4xx_tlbwe_hi();
5745 break;
5746 case 1:
f78fb44e
AJ
5747 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5748 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
76a66253
JM
5749 gen_op_4xx_tlbwe_lo();
5750 break;
5751 default:
e1833e1f 5752 GEN_EXCP_INVAL(ctx);
76a66253 5753 break;
9a64fbe4 5754 }
76a66253
JM
5755#endif
5756}
5757
a4bb6c3e 5758/* TLB management - PowerPC 440 implementation */
5eb7995e 5759/* tlbre */
c7697e1f 5760GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5761{
5762#if defined(CONFIG_USER_ONLY)
e1833e1f 5763 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5764#else
5765 if (unlikely(!ctx->supervisor)) {
e1833e1f 5766 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5767 return;
5768 }
5769 switch (rB(ctx->opcode)) {
5770 case 0:
5eb7995e 5771 case 1:
5eb7995e 5772 case 2:
f78fb44e 5773 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
a4bb6c3e 5774 gen_op_440_tlbre(rB(ctx->opcode));
f78fb44e 5775 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5776 break;
5777 default:
e1833e1f 5778 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5779 break;
5780 }
5781#endif
5782}
5783
5784/* tlbsx - tlbsx. */
c7697e1f 5785GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5eb7995e
JM
5786{
5787#if defined(CONFIG_USER_ONLY)
e1833e1f 5788 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5789#else
5790 if (unlikely(!ctx->supervisor)) {
e1833e1f 5791 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5792 return;
5793 }
e2be8d8d 5794 gen_addr_reg_index(cpu_T[0], ctx);
daf4f96e 5795 gen_op_440_tlbsx();
5eb7995e 5796 if (Rc(ctx->opcode))
daf4f96e 5797 gen_op_4xx_tlbsx_check();
f78fb44e 5798 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5eb7995e
JM
5799#endif
5800}
5801
5802/* tlbwe */
c7697e1f 5803GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5eb7995e
JM
5804{
5805#if defined(CONFIG_USER_ONLY)
e1833e1f 5806 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5807#else
5808 if (unlikely(!ctx->supervisor)) {
e1833e1f 5809 GEN_EXCP_PRIVOPC(ctx);
5eb7995e
JM
5810 return;
5811 }
5812 switch (rB(ctx->opcode)) {
5813 case 0:
5eb7995e 5814 case 1:
5eb7995e 5815 case 2:
f78fb44e
AJ
5816 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5817 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
a4bb6c3e 5818 gen_op_440_tlbwe(rB(ctx->opcode));
5eb7995e
JM
5819 break;
5820 default:
e1833e1f 5821 GEN_EXCP_INVAL(ctx);
5eb7995e
JM
5822 break;
5823 }
5824#endif
5825}
5826
76a66253 5827/* wrtee */
05332d70 5828GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
76a66253
JM
5829{
5830#if defined(CONFIG_USER_ONLY)
e1833e1f 5831 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5832#else
5833 if (unlikely(!ctx->supervisor)) {
e1833e1f 5834 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5835 return;
5836 }
f78fb44e 5837 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
a42bd6cc 5838 gen_op_wrte();
dee96f6c
JM
5839 /* Stop translation to have a chance to raise an exception
5840 * if we just set msr_ee to 1
5841 */
e1833e1f 5842 GEN_STOP(ctx);
76a66253
JM
5843#endif
5844}
5845
5846/* wrteei */
05332d70 5847GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
76a66253
JM
5848{
5849#if defined(CONFIG_USER_ONLY)
e1833e1f 5850 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5851#else
5852 if (unlikely(!ctx->supervisor)) {
e1833e1f 5853 GEN_EXCP_PRIVOPC(ctx);
76a66253
JM
5854 return;
5855 }
86c581dc 5856 tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
a42bd6cc 5857 gen_op_wrte();
dee96f6c
JM
5858 /* Stop translation to have a chance to raise an exception
5859 * if we just set msr_ee to 1
5860 */
e1833e1f 5861 GEN_STOP(ctx);
76a66253
JM
5862#endif
5863}
5864
08e46e54 5865/* PowerPC 440 specific instructions */
76a66253
JM
5866/* dlmzb */
5867GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5868{
f78fb44e
AJ
5869 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
5870 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
76a66253 5871 gen_op_440_dlmzb();
f78fb44e 5872 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
3d7b417e
AJ
5873 tcg_gen_andi_tl(cpu_xer, cpu_xer, ~0x7F);
5874 tcg_gen_or_tl(cpu_xer, cpu_xer, cpu_T[0]);
76a66253
JM
5875 if (Rc(ctx->opcode)) {
5876 gen_op_440_dlmzb_update_Rc();
a7812ae4
PB
5877 tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_T[0]);
5878 tcg_gen_andi_i32(cpu_crf[0], cpu_crf[0], 0xf);
76a66253
JM
5879 }
5880}
5881
5882/* mbar replaces eieio on 440 */
5883GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5884{
5885 /* interpreted as no-op */
5886}
5887
5888/* msync replaces sync on 440 */
0db1b20e 5889GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
76a66253
JM
5890{
5891 /* interpreted as no-op */
5892}
5893
5894/* icbt */
c7697e1f 5895GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
76a66253
JM
5896{
5897 /* interpreted as no-op */
5898 /* XXX: specification say this is treated as a load by the MMU
5899 * but does not generate any exception
5900 */
79aceca5
FB
5901}
5902
a9d9eb8f
JM
5903/*** Altivec vector extension ***/
5904/* Altivec registers moves */
a9d9eb8f 5905
a9d9eb8f 5906#define GEN_VR_LDX(name, opc2, opc3) \
fe1e5c53 5907GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
a9d9eb8f 5908{ \
fe1e5c53 5909 TCGv EA; \
a9d9eb8f
JM
5910 if (unlikely(!ctx->altivec_enabled)) { \
5911 GEN_EXCP_NO_VR(ctx); \
5912 return; \
5913 } \
fe1e5c53
AJ
5914 EA = tcg_temp_new(); \
5915 gen_addr_reg_index(EA, ctx); \
5916 tcg_gen_andi_tl(EA, EA, ~0xf); \
5917 if (ctx->mem_idx & 1) { \
5918 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5919 tcg_gen_addi_tl(EA, EA, 8); \
5920 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5921 } else { \
5922 gen_qemu_ld64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5923 tcg_gen_addi_tl(EA, EA, 8); \
5924 gen_qemu_ld64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5925 } \
5926 tcg_temp_free(EA); \
a9d9eb8f
JM
5927}
5928
5929#define GEN_VR_STX(name, opc2, opc3) \
5930GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5931{ \
fe1e5c53 5932 TCGv EA; \
a9d9eb8f
JM
5933 if (unlikely(!ctx->altivec_enabled)) { \
5934 GEN_EXCP_NO_VR(ctx); \
5935 return; \
5936 } \
fe1e5c53
AJ
5937 EA = tcg_temp_new(); \
5938 gen_addr_reg_index(EA, ctx); \
5939 tcg_gen_andi_tl(EA, EA, ~0xf); \
5940 if (ctx->mem_idx & 1) { \
5941 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5942 tcg_gen_addi_tl(EA, EA, 8); \
5943 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5944 } else { \
5945 gen_qemu_st64(cpu_avrh[rD(ctx->opcode)], EA, ctx->mem_idx); \
5946 tcg_gen_addi_tl(EA, EA, 8); \
5947 gen_qemu_st64(cpu_avrl[rD(ctx->opcode)], EA, ctx->mem_idx); \
5948 } \
5949 tcg_temp_free(EA); \
a9d9eb8f
JM
5950}
5951
fe1e5c53 5952GEN_VR_LDX(lvx, 0x07, 0x03);
a9d9eb8f 5953/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
fe1e5c53 5954GEN_VR_LDX(lvxl, 0x07, 0x0B);
a9d9eb8f 5955
fe1e5c53 5956GEN_VR_STX(svx, 0x07, 0x07);
a9d9eb8f 5957/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
fe1e5c53 5958GEN_VR_STX(svxl, 0x07, 0x0F);
a9d9eb8f 5959
0487d6a8 5960/*** SPE extension ***/
0487d6a8 5961/* Register moves */
3cd7d1dd 5962
a7812ae4 5963static always_inline void gen_load_gpr64(TCGv_i64 t, int reg) {
f78fb44e
AJ
5964#if defined(TARGET_PPC64)
5965 tcg_gen_mov_i64(t, cpu_gpr[reg]);
5966#else
36aa55dc 5967 tcg_gen_concat_i32_i64(t, cpu_gpr[reg], cpu_gprh[reg]);
3cd7d1dd 5968#endif
f78fb44e 5969}
3cd7d1dd 5970
a7812ae4 5971static always_inline void gen_store_gpr64(int reg, TCGv_i64 t) {
f78fb44e
AJ
5972#if defined(TARGET_PPC64)
5973 tcg_gen_mov_i64(cpu_gpr[reg], t);
5974#else
a7812ae4 5975 TCGv_i64 tmp = tcg_temp_new_i64();
f78fb44e 5976 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
f78fb44e
AJ
5977 tcg_gen_shri_i64(tmp, t, 32);
5978 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
a7812ae4 5979 tcg_temp_free_i64(tmp);
3cd7d1dd 5980#endif
f78fb44e 5981}
3cd7d1dd 5982
0487d6a8
JM
5983#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5984GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5985{ \
5986 if (Rc(ctx->opcode)) \
5987 gen_##name1(ctx); \
5988 else \
5989 gen_##name0(ctx); \
5990}
5991
5992/* Handler for undefined SPE opcodes */
b068d6a7 5993static always_inline void gen_speundef (DisasContext *ctx)
0487d6a8 5994{
e1833e1f 5995 GEN_EXCP_INVAL(ctx);
0487d6a8
JM
5996}
5997
57951c27
AJ
5998/* SPE logic */
5999#if defined(TARGET_PPC64)
6000#define GEN_SPEOP_LOGIC2(name, tcg_op) \
b068d6a7 6001static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6002{ \
6003 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6004 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6005 return; \
6006 } \
57951c27
AJ
6007 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6008 cpu_gpr[rB(ctx->opcode)]); \
6009}
6010#else
6011#define GEN_SPEOP_LOGIC2(name, tcg_op) \
6012static always_inline void gen_##name (DisasContext *ctx) \
6013{ \
6014 if (unlikely(!ctx->spe_enabled)) { \
6015 GEN_EXCP_NO_AP(ctx); \
6016 return; \
6017 } \
6018 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6019 cpu_gpr[rB(ctx->opcode)]); \
6020 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6021 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6022}
57951c27
AJ
6023#endif
6024
6025GEN_SPEOP_LOGIC2(evand, tcg_gen_and_tl);
6026GEN_SPEOP_LOGIC2(evandc, tcg_gen_andc_tl);
6027GEN_SPEOP_LOGIC2(evxor, tcg_gen_xor_tl);
6028GEN_SPEOP_LOGIC2(evor, tcg_gen_or_tl);
6029GEN_SPEOP_LOGIC2(evnor, tcg_gen_nor_tl);
6030GEN_SPEOP_LOGIC2(eveqv, tcg_gen_eqv_tl);
6031GEN_SPEOP_LOGIC2(evorc, tcg_gen_orc_tl);
6032GEN_SPEOP_LOGIC2(evnand, tcg_gen_nand_tl);
0487d6a8 6033
57951c27
AJ
6034/* SPE logic immediate */
6035#if defined(TARGET_PPC64)
6036#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
3d3a6a0a
AJ
6037static always_inline void gen_##name (DisasContext *ctx) \
6038{ \
6039 if (unlikely(!ctx->spe_enabled)) { \
6040 GEN_EXCP_NO_AP(ctx); \
6041 return; \
6042 } \
a7812ae4
PB
6043 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6044 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6045 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6046 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6047 tcg_opi(t0, t0, rB(ctx->opcode)); \
6048 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6049 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6050 tcg_temp_free_i64(t2); \
57951c27
AJ
6051 tcg_opi(t1, t1, rB(ctx->opcode)); \
6052 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6053 tcg_temp_free_i32(t0); \
6054 tcg_temp_free_i32(t1); \
3d3a6a0a 6055}
57951c27
AJ
6056#else
6057#define GEN_SPEOP_TCG_LOGIC_IMM2(name, tcg_opi) \
b068d6a7 6058static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6059{ \
6060 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6061 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6062 return; \
6063 } \
57951c27
AJ
6064 tcg_opi(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6065 rB(ctx->opcode)); \
6066 tcg_opi(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6067 rB(ctx->opcode)); \
0487d6a8 6068}
57951c27
AJ
6069#endif
6070GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
6071GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
6072GEN_SPEOP_TCG_LOGIC_IMM2(evsrwis, tcg_gen_sari_i32);
6073GEN_SPEOP_TCG_LOGIC_IMM2(evrlwi, tcg_gen_rotli_i32);
0487d6a8 6074
57951c27
AJ
6075/* SPE arithmetic */
6076#if defined(TARGET_PPC64)
6077#define GEN_SPEOP_ARITH1(name, tcg_op) \
b068d6a7 6078static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6079{ \
6080 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6081 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6082 return; \
6083 } \
a7812ae4
PB
6084 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6085 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6086 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6087 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6088 tcg_op(t0, t0); \
6089 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6090 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6091 tcg_temp_free_i64(t2); \
57951c27
AJ
6092 tcg_op(t1, t1); \
6093 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6094 tcg_temp_free_i32(t0); \
6095 tcg_temp_free_i32(t1); \
0487d6a8 6096}
57951c27 6097#else
a7812ae4 6098#define GEN_SPEOP_ARITH1(name, tcg_op) \
57951c27
AJ
6099static always_inline void gen_##name (DisasContext *ctx) \
6100{ \
6101 if (unlikely(!ctx->spe_enabled)) { \
6102 GEN_EXCP_NO_AP(ctx); \
6103 return; \
6104 } \
6105 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]); \
6106 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]); \
6107}
6108#endif
0487d6a8 6109
a7812ae4 6110static always_inline void gen_op_evabs (TCGv_i32 ret, TCGv_i32 arg1)
57951c27
AJ
6111{
6112 int l1 = gen_new_label();
6113 int l2 = gen_new_label();
0487d6a8 6114
57951c27
AJ
6115 tcg_gen_brcondi_i32(TCG_COND_GE, arg1, 0, l1);
6116 tcg_gen_neg_i32(ret, arg1);
6117 tcg_gen_br(l2);
6118 gen_set_label(l1);
a7812ae4 6119 tcg_gen_mov_i32(ret, arg1);
57951c27
AJ
6120 gen_set_label(l2);
6121}
6122GEN_SPEOP_ARITH1(evabs, gen_op_evabs);
6123GEN_SPEOP_ARITH1(evneg, tcg_gen_neg_i32);
6124GEN_SPEOP_ARITH1(evextsb, tcg_gen_ext8s_i32);
6125GEN_SPEOP_ARITH1(evextsh, tcg_gen_ext16s_i32);
a7812ae4 6126static always_inline void gen_op_evrndw (TCGv_i32 ret, TCGv_i32 arg1)
0487d6a8 6127{
57951c27
AJ
6128 tcg_gen_addi_i32(ret, arg1, 0x8000);
6129 tcg_gen_ext16u_i32(ret, ret);
6130}
6131GEN_SPEOP_ARITH1(evrndw, gen_op_evrndw);
a7812ae4
PB
6132GEN_SPEOP_ARITH1(evcntlsw, gen_helper_cntlsw32);
6133GEN_SPEOP_ARITH1(evcntlzw, gen_helper_cntlzw32);
0487d6a8 6134
57951c27
AJ
6135#if defined(TARGET_PPC64)
6136#define GEN_SPEOP_ARITH2(name, tcg_op) \
6137static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6138{ \
6139 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6140 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6141 return; \
6142 } \
a7812ae4
PB
6143 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6144 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6145 TCGv_i32 t2 = tcg_temp_local_new_i32(); \
6146 TCGv_i64 t3 = tcg_temp_local_new(TCG_TYPE_I64); \
57951c27
AJ
6147 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6148 tcg_gen_trunc_i64_i32(t2, cpu_gpr[rB(ctx->opcode)]); \
6149 tcg_op(t0, t0, t2); \
6150 tcg_gen_shri_i64(t3, cpu_gpr[rA(ctx->opcode)], 32); \
6151 tcg_gen_trunc_i64_i32(t1, t3); \
6152 tcg_gen_shri_i64(t3, cpu_gpr[rB(ctx->opcode)], 32); \
6153 tcg_gen_trunc_i64_i32(t2, t3); \
a7812ae4 6154 tcg_temp_free_i64(t3); \
57951c27 6155 tcg_op(t1, t1, t2); \
a7812ae4 6156 tcg_temp_free_i32(t2); \
57951c27 6157 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6158 tcg_temp_free_i32(t0); \
6159 tcg_temp_free_i32(t1); \
0487d6a8 6160}
57951c27
AJ
6161#else
6162#define GEN_SPEOP_ARITH2(name, tcg_op) \
6163static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8
JM
6164{ \
6165 if (unlikely(!ctx->spe_enabled)) { \
e1833e1f 6166 GEN_EXCP_NO_AP(ctx); \
0487d6a8
JM
6167 return; \
6168 } \
57951c27
AJ
6169 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
6170 cpu_gpr[rB(ctx->opcode)]); \
6171 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], \
6172 cpu_gprh[rB(ctx->opcode)]); \
0487d6a8 6173}
57951c27 6174#endif
0487d6a8 6175
a7812ae4 6176static always_inline void gen_op_evsrwu (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6177{
a7812ae4 6178 TCGv_i32 t0;
57951c27 6179 int l1, l2;
0487d6a8 6180
57951c27
AJ
6181 l1 = gen_new_label();
6182 l2 = gen_new_label();
a7812ae4 6183 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6184 /* No error here: 6 bits are used */
6185 tcg_gen_andi_i32(t0, arg2, 0x3F);
6186 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6187 tcg_gen_shr_i32(ret, arg1, t0);
6188 tcg_gen_br(l2);
6189 gen_set_label(l1);
6190 tcg_gen_movi_i32(ret, 0);
6191 tcg_gen_br(l2);
a7812ae4 6192 tcg_temp_free_i32(t0);
57951c27
AJ
6193}
6194GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
a7812ae4 6195static always_inline void gen_op_evsrws (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6196{
a7812ae4 6197 TCGv_i32 t0;
57951c27
AJ
6198 int l1, l2;
6199
6200 l1 = gen_new_label();
6201 l2 = gen_new_label();
a7812ae4 6202 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6203 /* No error here: 6 bits are used */
6204 tcg_gen_andi_i32(t0, arg2, 0x3F);
6205 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6206 tcg_gen_sar_i32(ret, arg1, t0);
6207 tcg_gen_br(l2);
6208 gen_set_label(l1);
6209 tcg_gen_movi_i32(ret, 0);
6210 tcg_gen_br(l2);
a7812ae4 6211 tcg_temp_free_i32(t0);
57951c27
AJ
6212}
6213GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
a7812ae4 6214static always_inline void gen_op_evslw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6215{
a7812ae4 6216 TCGv_i32 t0;
57951c27
AJ
6217 int l1, l2;
6218
6219 l1 = gen_new_label();
6220 l2 = gen_new_label();
a7812ae4 6221 t0 = tcg_temp_local_new_i32();
57951c27
AJ
6222 /* No error here: 6 bits are used */
6223 tcg_gen_andi_i32(t0, arg2, 0x3F);
6224 tcg_gen_brcondi_i32(TCG_COND_GE, t0, 32, l1);
6225 tcg_gen_shl_i32(ret, arg1, t0);
6226 tcg_gen_br(l2);
6227 gen_set_label(l1);
6228 tcg_gen_movi_i32(ret, 0);
6229 tcg_gen_br(l2);
a7812ae4 6230 tcg_temp_free_i32(t0);
57951c27
AJ
6231}
6232GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
a7812ae4 6233static always_inline void gen_op_evrlw (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
57951c27 6234{
a7812ae4 6235 TCGv_i32 t0 = tcg_temp_new_i32();
57951c27
AJ
6236 tcg_gen_andi_i32(t0, arg2, 0x1F);
6237 tcg_gen_rotl_i32(ret, arg1, t0);
a7812ae4 6238 tcg_temp_free_i32(t0);
57951c27
AJ
6239}
6240GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
6241static always_inline void gen_evmergehi (DisasContext *ctx)
6242{
6243 if (unlikely(!ctx->spe_enabled)) {
6244 GEN_EXCP_NO_AP(ctx);
6245 return;
6246 }
6247#if defined(TARGET_PPC64)
a7812ae4
PB
6248 TCGv t0 = tcg_temp_new();
6249 TCGv t1 = tcg_temp_new();
57951c27
AJ
6250 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6251 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6252 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6253 tcg_temp_free(t0);
6254 tcg_temp_free(t1);
6255#else
6256 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6257 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6258#endif
6259}
6260GEN_SPEOP_ARITH2(evaddw, tcg_gen_add_i32);
a7812ae4 6261static always_inline void gen_op_evsubf (TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
0487d6a8 6262{
57951c27
AJ
6263 tcg_gen_sub_i32(ret, arg2, arg1);
6264}
6265GEN_SPEOP_ARITH2(evsubfw, gen_op_evsubf);
0487d6a8 6266
57951c27
AJ
6267/* SPE arithmetic immediate */
6268#if defined(TARGET_PPC64)
6269#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6270static always_inline void gen_##name (DisasContext *ctx) \
6271{ \
6272 if (unlikely(!ctx->spe_enabled)) { \
6273 GEN_EXCP_NO_AP(ctx); \
6274 return; \
6275 } \
a7812ae4
PB
6276 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6277 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6278 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6279 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6280 tcg_op(t0, t0, rA(ctx->opcode)); \
6281 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6282 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6283 tcg_temp_free_i64(t2); \
57951c27
AJ
6284 tcg_op(t1, t1, rA(ctx->opcode)); \
6285 tcg_gen_concat_i32_i64(cpu_gpr[rD(ctx->opcode)], t0, t1); \
a7812ae4
PB
6286 tcg_temp_free_i32(t0); \
6287 tcg_temp_free_i32(t1); \
57951c27
AJ
6288}
6289#else
6290#define GEN_SPEOP_ARITH_IMM2(name, tcg_op) \
6291static always_inline void gen_##name (DisasContext *ctx) \
6292{ \
6293 if (unlikely(!ctx->spe_enabled)) { \
6294 GEN_EXCP_NO_AP(ctx); \
6295 return; \
6296 } \
6297 tcg_op(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
6298 rA(ctx->opcode)); \
6299 tcg_op(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)], \
6300 rA(ctx->opcode)); \
6301}
6302#endif
6303GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
6304GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
6305
6306/* SPE comparison */
6307#if defined(TARGET_PPC64)
6308#define GEN_SPEOP_COMP(name, tcg_cond) \
6309static always_inline void gen_##name (DisasContext *ctx) \
6310{ \
6311 if (unlikely(!ctx->spe_enabled)) { \
6312 GEN_EXCP_NO_AP(ctx); \
6313 return; \
6314 } \
6315 int l1 = gen_new_label(); \
6316 int l2 = gen_new_label(); \
6317 int l3 = gen_new_label(); \
6318 int l4 = gen_new_label(); \
a7812ae4
PB
6319 TCGv_i32 t0 = tcg_temp_local_new_i32(); \
6320 TCGv_i32 t1 = tcg_temp_local_new_i32(); \
6321 TCGv_i64 t2 = tcg_temp_local_new_i64(); \
57951c27
AJ
6322 tcg_gen_trunc_i64_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
6323 tcg_gen_trunc_i64_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
6324 tcg_gen_brcond_i32(tcg_cond, t0, t1, l1); \
a7812ae4 6325 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], 0); \
57951c27
AJ
6326 tcg_gen_br(l2); \
6327 gen_set_label(l1); \
6328 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6329 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6330 gen_set_label(l2); \
6331 tcg_gen_shri_i64(t2, cpu_gpr[rA(ctx->opcode)], 32); \
6332 tcg_gen_trunc_i64_i32(t0, t2); \
6333 tcg_gen_shri_i64(t2, cpu_gpr[rB(ctx->opcode)], 32); \
6334 tcg_gen_trunc_i64_i32(t1, t2); \
a7812ae4 6335 tcg_temp_free_i64(t2); \
57951c27
AJ
6336 tcg_gen_brcond_i32(tcg_cond, t0, t1, l3); \
6337 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6338 ~(CRF_CH | CRF_CH_AND_CL)); \
6339 tcg_gen_br(l4); \
6340 gen_set_label(l3); \
6341 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6342 CRF_CH | CRF_CH_OR_CL); \
6343 gen_set_label(l4); \
a7812ae4
PB
6344 tcg_temp_free_i32(t0); \
6345 tcg_temp_free_i32(t1); \
57951c27
AJ
6346}
6347#else
6348#define GEN_SPEOP_COMP(name, tcg_cond) \
6349static always_inline void gen_##name (DisasContext *ctx) \
6350{ \
6351 if (unlikely(!ctx->spe_enabled)) { \
6352 GEN_EXCP_NO_AP(ctx); \
6353 return; \
6354 } \
6355 int l1 = gen_new_label(); \
6356 int l2 = gen_new_label(); \
6357 int l3 = gen_new_label(); \
6358 int l4 = gen_new_label(); \
6359 \
6360 tcg_gen_brcond_i32(tcg_cond, cpu_gpr[rA(ctx->opcode)], \
6361 cpu_gpr[rB(ctx->opcode)], l1); \
6362 tcg_gen_movi_tl(cpu_crf[crfD(ctx->opcode)], 0); \
6363 tcg_gen_br(l2); \
6364 gen_set_label(l1); \
6365 tcg_gen_movi_i32(cpu_crf[crfD(ctx->opcode)], \
6366 CRF_CL | CRF_CH_OR_CL | CRF_CH_AND_CL); \
6367 gen_set_label(l2); \
6368 tcg_gen_brcond_i32(tcg_cond, cpu_gprh[rA(ctx->opcode)], \
6369 cpu_gprh[rB(ctx->opcode)], l3); \
6370 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6371 ~(CRF_CH | CRF_CH_AND_CL)); \
6372 tcg_gen_br(l4); \
6373 gen_set_label(l3); \
6374 tcg_gen_ori_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)], \
6375 CRF_CH | CRF_CH_OR_CL); \
6376 gen_set_label(l4); \
6377}
6378#endif
6379GEN_SPEOP_COMP(evcmpgtu, TCG_COND_GTU);
6380GEN_SPEOP_COMP(evcmpgts, TCG_COND_GT);
6381GEN_SPEOP_COMP(evcmpltu, TCG_COND_LTU);
6382GEN_SPEOP_COMP(evcmplts, TCG_COND_LT);
6383GEN_SPEOP_COMP(evcmpeq, TCG_COND_EQ);
6384
6385/* SPE misc */
6386static always_inline void gen_brinc (DisasContext *ctx)
6387{
6388 /* Note: brinc is usable even if SPE is disabled */
a7812ae4
PB
6389 gen_helper_brinc(cpu_gpr[rD(ctx->opcode)],
6390 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
0487d6a8 6391}
57951c27
AJ
6392static always_inline void gen_evmergelo (DisasContext *ctx)
6393{
6394 if (unlikely(!ctx->spe_enabled)) {
6395 GEN_EXCP_NO_AP(ctx);
6396 return;
6397 }
6398#if defined(TARGET_PPC64)
a7812ae4
PB
6399 TCGv t0 = tcg_temp_new();
6400 TCGv t1 = tcg_temp_new();
57951c27
AJ
6401 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6402 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6403 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6404 tcg_temp_free(t0);
6405 tcg_temp_free(t1);
6406#else
6407 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6408 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6409#endif
6410}
6411static always_inline void gen_evmergehilo (DisasContext *ctx)
6412{
6413 if (unlikely(!ctx->spe_enabled)) {
6414 GEN_EXCP_NO_AP(ctx);
6415 return;
6416 }
6417#if defined(TARGET_PPC64)
a7812ae4
PB
6418 TCGv t0 = tcg_temp_new();
6419 TCGv t1 = tcg_temp_new();
57951c27
AJ
6420 tcg_gen_andi_tl(t0, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFLL);
6421 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF0000000ULL);
6422 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6423 tcg_temp_free(t0);
6424 tcg_temp_free(t1);
6425#else
6426 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6427 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6428#endif
6429}
6430static always_inline void gen_evmergelohi (DisasContext *ctx)
6431{
6432 if (unlikely(!ctx->spe_enabled)) {
6433 GEN_EXCP_NO_AP(ctx);
6434 return;
6435 }
6436#if defined(TARGET_PPC64)
a7812ae4
PB
6437 TCGv t0 = tcg_temp_new();
6438 TCGv t1 = tcg_temp_new();
57951c27
AJ
6439 tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 32);
6440 tcg_gen_shli_tl(t1, cpu_gpr[rA(ctx->opcode)], 32);
6441 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t0, t1);
6442 tcg_temp_free(t0);
6443 tcg_temp_free(t1);
6444#else
6445 tcg_gen_mov_i32(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6446 tcg_gen_mov_i32(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6447#endif
6448}
6449static always_inline void gen_evsplati (DisasContext *ctx)
6450{
38d14952 6451 uint64_t imm = ((int32_t)(rA(ctx->opcode) << 11)) >> 27;
0487d6a8 6452
57951c27 6453#if defined(TARGET_PPC64)
38d14952 6454 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6455#else
6456 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6457 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6458#endif
6459}
b068d6a7 6460static always_inline void gen_evsplatfi (DisasContext *ctx)
0487d6a8 6461{
38d14952 6462 uint64_t imm = rA(ctx->opcode) << 11;
0487d6a8 6463
57951c27 6464#if defined(TARGET_PPC64)
38d14952 6465 tcg_gen_movi_tl(cpu_gpr[rD(ctx->opcode)], (imm << 32) | imm);
57951c27
AJ
6466#else
6467 tcg_gen_movi_i32(cpu_gpr[rD(ctx->opcode)], imm);
6468 tcg_gen_movi_i32(cpu_gprh[rD(ctx->opcode)], imm);
6469#endif
0487d6a8
JM
6470}
6471
57951c27
AJ
6472static always_inline void gen_evsel (DisasContext *ctx)
6473{
6474 int l1 = gen_new_label();
6475 int l2 = gen_new_label();
6476 int l3 = gen_new_label();
6477 int l4 = gen_new_label();
a7812ae4 6478 TCGv_i32 t0 = tcg_temp_local_new_i32();
57951c27 6479#if defined(TARGET_PPC64)
a7812ae4
PB
6480 TCGv t1 = tcg_temp_local_new();
6481 TCGv t2 = tcg_temp_local_new();
57951c27
AJ
6482#endif
6483 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
6484 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
6485#if defined(TARGET_PPC64)
6486 tcg_gen_andi_tl(t1, cpu_gpr[rA(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6487#else
6488 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)]);
6489#endif
6490 tcg_gen_br(l2);
6491 gen_set_label(l1);
6492#if defined(TARGET_PPC64)
6493 tcg_gen_andi_tl(t1, cpu_gpr[rB(ctx->opcode)], 0xFFFFFFFF00000000ULL);
6494#else
6495 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
6496#endif
6497 gen_set_label(l2);
6498 tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 2);
6499 tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l3);
6500#if defined(TARGET_PPC64)
6501 tcg_gen_andi_tl(t2, cpu_gpr[rA(ctx->opcode)], 0x00000000FFFFFFFFULL);
6502#else
6503 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
6504#endif
6505 tcg_gen_br(l4);
6506 gen_set_label(l3);
6507#if defined(TARGET_PPC64)
6508 tcg_gen_andi_tl(t2, cpu_gpr[rB(ctx->opcode)], 0x00000000FFFFFFFFULL);
6509#else
6510 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
6511#endif
6512 gen_set_label(l4);
a7812ae4 6513 tcg_temp_free_i32(t0);
57951c27
AJ
6514#if defined(TARGET_PPC64)
6515 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], t1, t2);
6516 tcg_temp_free(t1);
6517 tcg_temp_free(t2);
6518#endif
6519}
6520GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
6521{
6522 gen_evsel(ctx);
6523}
6524GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
6525{
6526 gen_evsel(ctx);
6527}
6528GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
6529{
6530 gen_evsel(ctx);
6531}
6532GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
6533{
6534 gen_evsel(ctx);
6535}
0487d6a8
JM
6536
6537GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
6538GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
6539GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
6540GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
6541GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
6542GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
6543GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
6544GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
6545GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
6546GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
6547GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
6548GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
6549GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
6550GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
6551GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
6552GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
6553GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
6554GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
6555GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
6556GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
6557GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
6558GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
6559GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
6560GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
6561GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
6562
6a6ae23f
AJ
6563/* SPE load and stores */
6564static always_inline void gen_addr_spe_imm_index (TCGv EA, DisasContext *ctx, int sh)
6565{
6566 target_ulong uimm = rB(ctx->opcode);
6567
6568 if (rA(ctx->opcode) == 0)
6569 tcg_gen_movi_tl(EA, uimm << sh);
6570 else
6571 tcg_gen_addi_tl(EA, cpu_gpr[rA(ctx->opcode)], uimm << sh);
0487d6a8 6572}
6a6ae23f
AJ
6573
6574static always_inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
6575{
6576#if defined(TARGET_PPC64)
6577 gen_qemu_ld64(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6578#else
6579 TCGv_i64 t0 = tcg_temp_new_i64();
6580 gen_qemu_ld64(t0, addr, ctx->mem_idx);
6581 tcg_gen_trunc_i64_i32(cpu_gpr[rD(ctx->opcode)], t0);
6582 tcg_gen_shri_i64(t0, t0, 32);
6583 tcg_gen_trunc_i64_i32(cpu_gprh[rD(ctx->opcode)], t0);
6584 tcg_temp_free_i64(t0);
6585#endif
0487d6a8 6586}
6a6ae23f
AJ
6587
6588static always_inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
6589{
0487d6a8 6590#if defined(TARGET_PPC64)
6a6ae23f
AJ
6591 TCGv t0 = tcg_temp_new();
6592 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6593 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6594 tcg_gen_addi_tl(addr, addr, 4);
6595 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
6596 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6597 tcg_temp_free(t0);
6598#else
6599 gen_qemu_ld32u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6600 tcg_gen_addi_tl(addr, addr, 4);
6601 gen_qemu_ld32u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6602#endif
0487d6a8 6603}
6a6ae23f
AJ
6604
6605static always_inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
6606{
6607 TCGv t0 = tcg_temp_new();
6608#if defined(TARGET_PPC64)
6609 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6610 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6611 tcg_gen_addi_tl(addr, addr, 2);
6612 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6613 tcg_gen_shli_tl(t0, t0, 32);
6614 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6615 tcg_gen_addi_tl(addr, addr, 2);
6616 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6617 tcg_gen_shli_tl(t0, t0, 16);
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_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6622#else
6a6ae23f
AJ
6623 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6624 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6625 tcg_gen_addi_tl(addr, addr, 2);
6626 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6627 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6628 tcg_gen_addi_tl(addr, addr, 2);
6629 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6630 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6631 tcg_gen_addi_tl(addr, addr, 2);
6632 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6633 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
0487d6a8 6634#endif
6a6ae23f 6635 tcg_temp_free(t0);
0487d6a8
JM
6636}
6637
6a6ae23f
AJ
6638static always_inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
6639{
6640 TCGv t0 = tcg_temp_new();
6641 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6642#if defined(TARGET_PPC64)
6643 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6644 tcg_gen_shli_tl(t0, t0, 16);
6645 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6646#else
6647 tcg_gen_shli_tl(t0, t0, 16);
6648 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6649 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6650#endif
6651 tcg_temp_free(t0);
0487d6a8
JM
6652}
6653
6a6ae23f
AJ
6654static always_inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
6655{
6656 TCGv t0 = tcg_temp_new();
6657 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6658#if defined(TARGET_PPC64)
6659 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6660 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6661#else
6662 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6663 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6664#endif
6665 tcg_temp_free(t0);
0487d6a8
JM
6666}
6667
6a6ae23f
AJ
6668static always_inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
6669{
6670 TCGv t0 = tcg_temp_new();
6671 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6672#if defined(TARGET_PPC64)
6673 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6674 tcg_gen_ext32u_tl(t0, t0);
6675 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6676#else
6677 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6678 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6679#endif
6680 tcg_temp_free(t0);
6681}
6682
6683static always_inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
6684{
6685 TCGv t0 = tcg_temp_new();
6686#if defined(TARGET_PPC64)
6687 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6688 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6689 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6690 tcg_gen_shli_tl(t0, t0, 16);
6691 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6692#else
6693 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6694 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6695 tcg_gen_addi_tl(addr, addr, 2);
6696 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6697 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6698#endif
6699 tcg_temp_free(t0);
6700}
6701
6702static always_inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
6703{
6704#if defined(TARGET_PPC64)
6705 TCGv t0 = tcg_temp_new();
6706 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6707 tcg_gen_addi_tl(addr, addr, 2);
6708 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6709 tcg_gen_shli_tl(t0, t0, 32);
6710 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6711 tcg_temp_free(t0);
6712#else
6713 gen_qemu_ld16u(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6714 tcg_gen_addi_tl(addr, addr, 2);
6715 gen_qemu_ld16u(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6716#endif
6717}
6718
6719static always_inline void gen_op_evlwhos(DisasContext *ctx, TCGv addr)
6720{
6721#if defined(TARGET_PPC64)
6722 TCGv t0 = tcg_temp_new();
6723 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6724 tcg_gen_ext32u_tl(cpu_gpr[rD(ctx->opcode)], t0);
6725 tcg_gen_addi_tl(addr, addr, 2);
6726 gen_qemu_ld16s(t0, addr, ctx->mem_idx);
6727 tcg_gen_shli_tl(t0, t0, 32);
6728 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6729 tcg_temp_free(t0);
6730#else
6731 gen_qemu_ld16s(cpu_gprh[rD(ctx->opcode)], addr, ctx->mem_idx);
6732 tcg_gen_addi_tl(addr, addr, 2);
6733 gen_qemu_ld16s(cpu_gpr[rD(ctx->opcode)], addr, ctx->mem_idx);
6734#endif
6735}
6736
6737static always_inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
6738{
6739 TCGv t0 = tcg_temp_new();
6740 gen_qemu_ld32u(t0, addr, ctx->mem_idx);
0487d6a8 6741#if defined(TARGET_PPC64)
6a6ae23f
AJ
6742 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 32);
6743 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6744#else
6745 tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
6746 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
6747#endif
6748 tcg_temp_free(t0);
6749}
6750
6751static always_inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
6752{
6753 TCGv t0 = tcg_temp_new();
6754#if defined(TARGET_PPC64)
6755 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6756 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 48);
6757 tcg_gen_shli_tl(t0, t0, 32);
6758 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6759 tcg_gen_addi_tl(addr, addr, 2);
6760 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6761 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6762 tcg_gen_shli_tl(t0, t0, 16);
6763 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
6764#else
6765 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6766 tcg_gen_shli_tl(cpu_gprh[rD(ctx->opcode)], t0, 16);
6767 tcg_gen_or_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
6768 tcg_gen_addi_tl(addr, addr, 2);
6769 gen_qemu_ld16u(t0, addr, ctx->mem_idx);
6770 tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
6771 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
0487d6a8 6772#endif
6a6ae23f
AJ
6773 tcg_temp_free(t0);
6774}
6775
6776static always_inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
6777{
6778#if defined(TARGET_PPC64)
6779 gen_qemu_st64(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
0487d6a8 6780#else
6a6ae23f
AJ
6781 TCGv_i64 t0 = tcg_temp_new_i64();
6782 tcg_gen_concat_i32_i64(t0, cpu_gpr[rS(ctx->opcode)], cpu_gprh[rS(ctx->opcode)]);
6783 gen_qemu_st64(t0, addr, ctx->mem_idx);
6784 tcg_temp_free_i64(t0);
6785#endif
6786}
6787
6788static always_inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
6789{
0487d6a8 6790#if defined(TARGET_PPC64)
6a6ae23f
AJ
6791 TCGv t0 = tcg_temp_new();
6792 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6793 gen_qemu_st32(t0, addr, ctx->mem_idx);
6794 tcg_temp_free(t0);
6795#else
6796 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6797#endif
6798 tcg_gen_addi_tl(addr, addr, 4);
6799 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6800}
6801
6802static always_inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
6803{
6804 TCGv t0 = tcg_temp_new();
6805#if defined(TARGET_PPC64)
6806 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6807#else
6808 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6809#endif
6810 gen_qemu_st16(t0, addr, ctx->mem_idx);
6811 tcg_gen_addi_tl(addr, addr, 2);
6812#if defined(TARGET_PPC64)
6813 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6814 gen_qemu_st16(t0, addr, ctx->mem_idx);
6815#else
6816 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6817#endif
6818 tcg_gen_addi_tl(addr, addr, 2);
6819 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6820 gen_qemu_st16(t0, addr, ctx->mem_idx);
6821 tcg_temp_free(t0);
6822 tcg_gen_addi_tl(addr, addr, 2);
6823 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6824}
6825
6826static always_inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
6827{
6828 TCGv t0 = tcg_temp_new();
6829#if defined(TARGET_PPC64)
6830 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 48);
6831#else
6832 tcg_gen_shri_tl(t0, cpu_gprh[rS(ctx->opcode)], 16);
6833#endif
6834 gen_qemu_st16(t0, addr, ctx->mem_idx);
6835 tcg_gen_addi_tl(addr, addr, 2);
6836 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
6837 gen_qemu_st16(t0, addr, ctx->mem_idx);
6838 tcg_temp_free(t0);
6839}
6840
6841static always_inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
6842{
6843#if defined(TARGET_PPC64)
6844 TCGv t0 = tcg_temp_new();
6845 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6846 gen_qemu_st16(t0, addr, ctx->mem_idx);
6847 tcg_temp_free(t0);
6848#else
6849 gen_qemu_st16(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6850#endif
6851 tcg_gen_addi_tl(addr, addr, 2);
6852 gen_qemu_st16(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6853}
6854
6855static always_inline void gen_op_evstwwe(DisasContext *ctx, TCGv addr)
6856{
6857#if defined(TARGET_PPC64)
6858 TCGv t0 = tcg_temp_new();
6859 tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 32);
6860 gen_qemu_st32(t0, addr, ctx->mem_idx);
6861 tcg_temp_free(t0);
6862#else
6863 gen_qemu_st32(cpu_gprh[rS(ctx->opcode)], addr, ctx->mem_idx);
6864#endif
6865}
6866
6867static always_inline void gen_op_evstwwo(DisasContext *ctx, TCGv addr)
6868{
6869 gen_qemu_st32(cpu_gpr[rS(ctx->opcode)], addr, ctx->mem_idx);
6870}
6871
6872#define GEN_SPEOP_LDST(name, opc2, sh) \
6873GEN_HANDLER(gen_##name, 0x04, opc2, 0x0C, 0x00000000, PPC_SPE) \
6874{ \
6875 TCGv t0; \
6876 if (unlikely(!ctx->spe_enabled)) { \
6877 GEN_EXCP_NO_AP(ctx); \
6878 return; \
6879 } \
6880 t0 = tcg_temp_new(); \
6881 if (Rc(ctx->opcode)) { \
6882 gen_addr_spe_imm_index(t0, ctx, sh); \
6883 } else { \
6884 gen_addr_reg_index(t0, ctx); \
6885 } \
6886 gen_op_##name(ctx, t0); \
6887 tcg_temp_free(t0); \
6888}
6889
6890GEN_SPEOP_LDST(evldd, 0x00, 3);
6891GEN_SPEOP_LDST(evldw, 0x01, 3);
6892GEN_SPEOP_LDST(evldh, 0x02, 3);
6893GEN_SPEOP_LDST(evlhhesplat, 0x04, 1);
6894GEN_SPEOP_LDST(evlhhousplat, 0x06, 1);
6895GEN_SPEOP_LDST(evlhhossplat, 0x07, 1);
6896GEN_SPEOP_LDST(evlwhe, 0x08, 2);
6897GEN_SPEOP_LDST(evlwhou, 0x0A, 2);
6898GEN_SPEOP_LDST(evlwhos, 0x0B, 2);
6899GEN_SPEOP_LDST(evlwwsplat, 0x0C, 2);
6900GEN_SPEOP_LDST(evlwhsplat, 0x0E, 2);
6901
6902GEN_SPEOP_LDST(evstdd, 0x10, 3);
6903GEN_SPEOP_LDST(evstdw, 0x11, 3);
6904GEN_SPEOP_LDST(evstdh, 0x12, 3);
6905GEN_SPEOP_LDST(evstwhe, 0x18, 2);
6906GEN_SPEOP_LDST(evstwho, 0x1A, 2);
6907GEN_SPEOP_LDST(evstwwe, 0x1C, 2);
6908GEN_SPEOP_LDST(evstwwo, 0x1E, 2);
0487d6a8
JM
6909
6910/* Multiply and add - TODO */
6911#if 0
6912GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
6913GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
6914GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
6915GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
6916GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
6917GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
6918GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
6919GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
6920GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
6921GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
6922GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
6923GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
6924
6925GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
6926GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
6927GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
6928GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
6929GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
6930GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
6931GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
6932GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
6933GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
6934GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
6935GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
6936GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
6937GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
6938GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
6939
6940GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
6941GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
6942GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
6943GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
6944GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
6945GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
6946
6947GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
6948GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
6949GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
6950GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
6951GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
6952GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
6953GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
6954GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
6955GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
6956GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
6957GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
6958GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
6959
6960GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
6961GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
6962GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
6963GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
6964GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
6965
6966GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
6967GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
6968GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
6969GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
6970GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
6971GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
6972GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
6973GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
6974GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
6975GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
6976GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
6977GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
6978
6979GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
6980GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
6981GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
6982GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
6983GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
6984#endif
6985
6986/*** SPE floating-point extension ***/
1c97856d
AJ
6987#if defined(TARGET_PPC64)
6988#define GEN_SPEFPUOP_CONV_32_32(name) \
b068d6a7 6989static always_inline void gen_##name (DisasContext *ctx) \
0487d6a8 6990{ \
1c97856d
AJ
6991 TCGv_i32 t0; \
6992 TCGv t1; \
6993 t0 = tcg_temp_new_i32(); \
6994 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
6995 gen_helper_##name(t0, t0); \
6996 t1 = tcg_temp_new(); \
6997 tcg_gen_extu_i32_tl(t1, t0); \
6998 tcg_temp_free_i32(t0); \
6999 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7000 0xFFFFFFFF00000000ULL); \
7001 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7002 tcg_temp_free(t1); \
0487d6a8 7003}
1c97856d
AJ
7004#define GEN_SPEFPUOP_CONV_32_64(name) \
7005static always_inline void gen_##name (DisasContext *ctx) \
7006{ \
7007 TCGv_i32 t0; \
7008 TCGv t1; \
7009 t0 = tcg_temp_new_i32(); \
7010 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7011 t1 = tcg_temp_new(); \
7012 tcg_gen_extu_i32_tl(t1, t0); \
7013 tcg_temp_free_i32(t0); \
7014 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7015 0xFFFFFFFF00000000ULL); \
7016 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t1); \
7017 tcg_temp_free(t1); \
7018}
7019#define GEN_SPEFPUOP_CONV_64_32(name) \
7020static always_inline void gen_##name (DisasContext *ctx) \
7021{ \
7022 TCGv_i32 t0 = tcg_temp_new_i32(); \
7023 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
7024 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7025 tcg_temp_free_i32(t0); \
7026}
7027#define GEN_SPEFPUOP_CONV_64_64(name) \
7028static always_inline void gen_##name (DisasContext *ctx) \
7029{ \
7030 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7031}
7032#define GEN_SPEFPUOP_ARITH2_32_32(name) \
57951c27
AJ
7033static always_inline void gen_##name (DisasContext *ctx) \
7034{ \
1c97856d
AJ
7035 TCGv_i32 t0, t1; \
7036 TCGv_i64 t2; \
57951c27
AJ
7037 if (unlikely(!ctx->spe_enabled)) { \
7038 GEN_EXCP_NO_AP(ctx); \
7039 return; \
7040 } \
1c97856d
AJ
7041 t0 = tcg_temp_new_i32(); \
7042 t1 = tcg_temp_new_i32(); \
7043 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7044 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7045 gen_helper_##name(t0, t0, t1); \
7046 tcg_temp_free_i32(t1); \
7047 t2 = tcg_temp_new(); \
7048 tcg_gen_extu_i32_tl(t2, t0); \
7049 tcg_temp_free_i32(t0); \
7050 tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], \
7051 0xFFFFFFFF00000000ULL); \
7052 tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t2); \
7053 tcg_temp_free(t2); \
57951c27 7054}
1c97856d 7055#define GEN_SPEFPUOP_ARITH2_64_64(name) \
57951c27
AJ
7056static always_inline void gen_##name (DisasContext *ctx) \
7057{ \
7058 if (unlikely(!ctx->spe_enabled)) { \
7059 GEN_EXCP_NO_AP(ctx); \
7060 return; \
7061 } \
1c97856d
AJ
7062 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], \
7063 cpu_gpr[rB(ctx->opcode)]); \
57951c27 7064}
1c97856d 7065#define GEN_SPEFPUOP_COMP_32(name) \
57951c27
AJ
7066static always_inline void gen_##name (DisasContext *ctx) \
7067{ \
1c97856d 7068 TCGv_i32 t0, t1; \
57951c27
AJ
7069 if (unlikely(!ctx->spe_enabled)) { \
7070 GEN_EXCP_NO_AP(ctx); \
7071 return; \
7072 } \
1c97856d
AJ
7073 t0 = tcg_temp_new_i32(); \
7074 t1 = tcg_temp_new_i32(); \
7075 tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
7076 tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
7077 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7078 tcg_temp_free_i32(t0); \
7079 tcg_temp_free_i32(t1); \
7080}
7081#define GEN_SPEFPUOP_COMP_64(name) \
7082static always_inline void gen_##name (DisasContext *ctx) \
7083{ \
7084 if (unlikely(!ctx->spe_enabled)) { \
7085 GEN_EXCP_NO_AP(ctx); \
7086 return; \
7087 } \
7088 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7089 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7090}
7091#else
7092#define GEN_SPEFPUOP_CONV_32_32(name) \
7093static always_inline void gen_##name (DisasContext *ctx) \
7094{ \
7095 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
57951c27 7096}
1c97856d
AJ
7097#define GEN_SPEFPUOP_CONV_32_64(name) \
7098static always_inline void gen_##name (DisasContext *ctx) \
7099{ \
7100 TCGv_i64 t0 = tcg_temp_new_i64(); \
7101 gen_load_gpr64(t0, rB(ctx->opcode)); \
7102 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], t0); \
7103 tcg_temp_free_i64(t0); \
7104}
7105#define GEN_SPEFPUOP_CONV_64_32(name) \
7106static always_inline void gen_##name (DisasContext *ctx) \
7107{ \
7108 TCGv_i64 t0 = tcg_temp_new_i64(); \
7109 gen_helper_##name(t0, cpu_gpr[rB(ctx->opcode)]); \
7110 gen_store_gpr64(rD(ctx->opcode), t0); \
7111 tcg_temp_free_i64(t0); \
7112}
7113#define GEN_SPEFPUOP_CONV_64_64(name) \
7114static always_inline void gen_##name (DisasContext *ctx) \
7115{ \
7116 TCGv_i64 t0 = tcg_temp_new_i64(); \
7117 gen_load_gpr64(t0, rB(ctx->opcode)); \
7118 gen_helper_##name(t0, t0); \
7119 gen_store_gpr64(rD(ctx->opcode), t0); \
7120 tcg_temp_free_i64(t0); \
7121}
7122#define GEN_SPEFPUOP_ARITH2_32_32(name) \
7123static always_inline void gen_##name (DisasContext *ctx) \
7124{ \
7125 if (unlikely(!ctx->spe_enabled)) { \
7126 GEN_EXCP_NO_AP(ctx); \
7127 return; \
7128 } \
7129 gen_helper_##name(cpu_gpr[rD(ctx->opcode)], \
7130 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7131}
7132#define GEN_SPEFPUOP_ARITH2_64_64(name) \
7133static always_inline void gen_##name (DisasContext *ctx) \
7134{ \
7135 TCGv_i64 t0, t1; \
7136 if (unlikely(!ctx->spe_enabled)) { \
7137 GEN_EXCP_NO_AP(ctx); \
7138 return; \
7139 } \
7140 t0 = tcg_temp_new_i64(); \
7141 t1 = tcg_temp_new_i64(); \
7142 gen_load_gpr64(t0, rA(ctx->opcode)); \
7143 gen_load_gpr64(t1, rB(ctx->opcode)); \
7144 gen_helper_##name(t0, t0, t1); \
7145 gen_store_gpr64(rD(ctx->opcode), t0); \
7146 tcg_temp_free_i64(t0); \
7147 tcg_temp_free_i64(t1); \
7148}
7149#define GEN_SPEFPUOP_COMP_32(name) \
7150static always_inline void gen_##name (DisasContext *ctx) \
7151{ \
7152 if (unlikely(!ctx->spe_enabled)) { \
7153 GEN_EXCP_NO_AP(ctx); \
7154 return; \
7155 } \
7156 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
7157 cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]); \
7158}
7159#define GEN_SPEFPUOP_COMP_64(name) \
7160static always_inline void gen_##name (DisasContext *ctx) \
7161{ \
7162 TCGv_i64 t0, t1; \
7163 if (unlikely(!ctx->spe_enabled)) { \
7164 GEN_EXCP_NO_AP(ctx); \
7165 return; \
7166 } \
7167 t0 = tcg_temp_new_i64(); \
7168 t1 = tcg_temp_new_i64(); \
7169 gen_load_gpr64(t0, rA(ctx->opcode)); \
7170 gen_load_gpr64(t1, rB(ctx->opcode)); \
7171 gen_helper_##name(cpu_crf[crfD(ctx->opcode)], t0, t1); \
7172 tcg_temp_free_i64(t0); \
7173 tcg_temp_free_i64(t1); \
7174}
7175#endif
57951c27 7176
0487d6a8
JM
7177/* Single precision floating-point vectors operations */
7178/* Arithmetic */
1c97856d
AJ
7179GEN_SPEFPUOP_ARITH2_64_64(evfsadd);
7180GEN_SPEFPUOP_ARITH2_64_64(evfssub);
7181GEN_SPEFPUOP_ARITH2_64_64(evfsmul);
7182GEN_SPEFPUOP_ARITH2_64_64(evfsdiv);
7183static always_inline void gen_evfsabs (DisasContext *ctx)
7184{
7185 if (unlikely(!ctx->spe_enabled)) {
7186 GEN_EXCP_NO_AP(ctx);
7187 return;
7188 }
7189#if defined(TARGET_PPC64)
7190 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
7191#else
7192 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
7193 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7194#endif
7195}
7196static always_inline void gen_evfsnabs (DisasContext *ctx)
7197{
7198 if (unlikely(!ctx->spe_enabled)) {
7199 GEN_EXCP_NO_AP(ctx);
7200 return;
7201 }
7202#if defined(TARGET_PPC64)
7203 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7204#else
7205 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7206 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7207#endif
7208}
7209static always_inline void gen_evfsneg (DisasContext *ctx)
7210{
7211 if (unlikely(!ctx->spe_enabled)) {
7212 GEN_EXCP_NO_AP(ctx);
7213 return;
7214 }
7215#if defined(TARGET_PPC64)
7216 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
7217#else
7218 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7219 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7220#endif
7221}
7222
0487d6a8 7223/* Conversion */
1c97856d
AJ
7224GEN_SPEFPUOP_CONV_64_64(evfscfui);
7225GEN_SPEFPUOP_CONV_64_64(evfscfsi);
7226GEN_SPEFPUOP_CONV_64_64(evfscfuf);
7227GEN_SPEFPUOP_CONV_64_64(evfscfsf);
7228GEN_SPEFPUOP_CONV_64_64(evfsctui);
7229GEN_SPEFPUOP_CONV_64_64(evfsctsi);
7230GEN_SPEFPUOP_CONV_64_64(evfsctuf);
7231GEN_SPEFPUOP_CONV_64_64(evfsctsf);
7232GEN_SPEFPUOP_CONV_64_64(evfsctuiz);
7233GEN_SPEFPUOP_CONV_64_64(evfsctsiz);
7234
0487d6a8 7235/* Comparison */
1c97856d
AJ
7236GEN_SPEFPUOP_COMP_64(evfscmpgt);
7237GEN_SPEFPUOP_COMP_64(evfscmplt);
7238GEN_SPEFPUOP_COMP_64(evfscmpeq);
7239GEN_SPEFPUOP_COMP_64(evfststgt);
7240GEN_SPEFPUOP_COMP_64(evfststlt);
7241GEN_SPEFPUOP_COMP_64(evfststeq);
0487d6a8
JM
7242
7243/* Opcodes definitions */
7244GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
7245GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
7246GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
7247GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
7248GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
7249GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
7250GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
7251GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
7252GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
7253GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
7254GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
7255GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
7256GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
7257GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
7258
7259/* Single precision floating-point operations */
7260/* Arithmetic */
1c97856d
AJ
7261GEN_SPEFPUOP_ARITH2_32_32(efsadd);
7262GEN_SPEFPUOP_ARITH2_32_32(efssub);
7263GEN_SPEFPUOP_ARITH2_32_32(efsmul);
7264GEN_SPEFPUOP_ARITH2_32_32(efsdiv);
7265static always_inline void gen_efsabs (DisasContext *ctx)
7266{
7267 if (unlikely(!ctx->spe_enabled)) {
7268 GEN_EXCP_NO_AP(ctx);
7269 return;
7270 }
7271 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
7272}
7273static always_inline void gen_efsnabs (DisasContext *ctx)
7274{
7275 if (unlikely(!ctx->spe_enabled)) {
7276 GEN_EXCP_NO_AP(ctx);
7277 return;
7278 }
7279 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7280}
7281static always_inline void gen_efsneg (DisasContext *ctx)
7282{
7283 if (unlikely(!ctx->spe_enabled)) {
7284 GEN_EXCP_NO_AP(ctx);
7285 return;
7286 }
7287 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
7288}
7289
0487d6a8 7290/* Conversion */
1c97856d
AJ
7291GEN_SPEFPUOP_CONV_32_32(efscfui);
7292GEN_SPEFPUOP_CONV_32_32(efscfsi);
7293GEN_SPEFPUOP_CONV_32_32(efscfuf);
7294GEN_SPEFPUOP_CONV_32_32(efscfsf);
7295GEN_SPEFPUOP_CONV_32_32(efsctui);
7296GEN_SPEFPUOP_CONV_32_32(efsctsi);
7297GEN_SPEFPUOP_CONV_32_32(efsctuf);
7298GEN_SPEFPUOP_CONV_32_32(efsctsf);
7299GEN_SPEFPUOP_CONV_32_32(efsctuiz);
7300GEN_SPEFPUOP_CONV_32_32(efsctsiz);
7301GEN_SPEFPUOP_CONV_32_64(efscfd);
7302
0487d6a8 7303/* Comparison */
1c97856d
AJ
7304GEN_SPEFPUOP_COMP_32(efscmpgt);
7305GEN_SPEFPUOP_COMP_32(efscmplt);
7306GEN_SPEFPUOP_COMP_32(efscmpeq);
7307GEN_SPEFPUOP_COMP_32(efststgt);
7308GEN_SPEFPUOP_COMP_32(efststlt);
7309GEN_SPEFPUOP_COMP_32(efststeq);
0487d6a8
JM
7310
7311/* Opcodes definitions */
05332d70 7312GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
0487d6a8
JM
7313GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
7314GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
7315GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
7316GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
7317GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
7318GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
7319GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
7320GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
7321GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
9ceb2a77
TS
7322GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
7323GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
0487d6a8
JM
7324GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
7325GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
7326
7327/* Double precision floating-point operations */
7328/* Arithmetic */
1c97856d
AJ
7329GEN_SPEFPUOP_ARITH2_64_64(efdadd);
7330GEN_SPEFPUOP_ARITH2_64_64(efdsub);
7331GEN_SPEFPUOP_ARITH2_64_64(efdmul);
7332GEN_SPEFPUOP_ARITH2_64_64(efddiv);
7333static always_inline void gen_efdabs (DisasContext *ctx)
7334{
7335 if (unlikely(!ctx->spe_enabled)) {
7336 GEN_EXCP_NO_AP(ctx);
7337 return;
7338 }
7339#if defined(TARGET_PPC64)
7340 tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
7341#else
7342 tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
7343#endif
7344}
7345static always_inline void gen_efdnabs (DisasContext *ctx)
7346{
7347 if (unlikely(!ctx->spe_enabled)) {
7348 GEN_EXCP_NO_AP(ctx);
7349 return;
7350 }
7351#if defined(TARGET_PPC64)
7352 tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7353#else
7354 tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7355#endif
7356}
7357static always_inline void gen_efdneg (DisasContext *ctx)
7358{
7359 if (unlikely(!ctx->spe_enabled)) {
7360 GEN_EXCP_NO_AP(ctx);
7361 return;
7362 }
7363#if defined(TARGET_PPC64)
7364 tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
7365#else
7366 tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
7367#endif
7368}
7369
0487d6a8 7370/* Conversion */
1c97856d
AJ
7371GEN_SPEFPUOP_CONV_64_32(efdcfui);
7372GEN_SPEFPUOP_CONV_64_32(efdcfsi);
7373GEN_SPEFPUOP_CONV_64_32(efdcfuf);
7374GEN_SPEFPUOP_CONV_64_32(efdcfsf);
7375GEN_SPEFPUOP_CONV_32_64(efdctui);
7376GEN_SPEFPUOP_CONV_32_64(efdctsi);
7377GEN_SPEFPUOP_CONV_32_64(efdctuf);
7378GEN_SPEFPUOP_CONV_32_64(efdctsf);
7379GEN_SPEFPUOP_CONV_32_64(efdctuiz);
7380GEN_SPEFPUOP_CONV_32_64(efdctsiz);
7381GEN_SPEFPUOP_CONV_64_32(efdcfs);
7382GEN_SPEFPUOP_CONV_64_64(efdcfuid);
7383GEN_SPEFPUOP_CONV_64_64(efdcfsid);
7384GEN_SPEFPUOP_CONV_64_64(efdctuidz);
7385GEN_SPEFPUOP_CONV_64_64(efdctsidz);
0487d6a8 7386
0487d6a8 7387/* Comparison */
1c97856d
AJ
7388GEN_SPEFPUOP_COMP_64(efdcmpgt);
7389GEN_SPEFPUOP_COMP_64(efdcmplt);
7390GEN_SPEFPUOP_COMP_64(efdcmpeq);
7391GEN_SPEFPUOP_COMP_64(efdtstgt);
7392GEN_SPEFPUOP_COMP_64(efdtstlt);
7393GEN_SPEFPUOP_COMP_64(efdtsteq);
0487d6a8
JM
7394
7395/* Opcodes definitions */
7396GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
7397GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
7398GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
7399GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
7400GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
7401GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
7402GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
7403GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
7404GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
7405GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
7406GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
7407GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
7408GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
7409GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
7410GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
7411GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
0487d6a8 7412
79aceca5
FB
7413/* End opcode list */
7414GEN_OPCODE_MARK(end);
7415
3fc6c082 7416#include "translate_init.c"
0411a972 7417#include "helper_regs.h"
79aceca5 7418
9a64fbe4 7419/*****************************************************************************/
3fc6c082 7420/* Misc PowerPC helpers */
36081602
JM
7421void cpu_dump_state (CPUState *env, FILE *f,
7422 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7423 int flags)
79aceca5 7424{
3fc6c082
FB
7425#define RGPL 4
7426#define RFPL 4
3fc6c082 7427
79aceca5
FB
7428 int i;
7429
077fc206 7430 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
3d7b417e 7431 env->nip, env->lr, env->ctr, env->xer);
6b542af7
JM
7432 cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
7433 env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
d9bce9d9 7434#if !defined(NO_TIMER_DUMP)
077fc206 7435 cpu_fprintf(f, "TB %08x %08x "
76a66253
JM
7436#if !defined(CONFIG_USER_ONLY)
7437 "DECR %08x"
7438#endif
7439 "\n",
077fc206 7440 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
76a66253
JM
7441#if !defined(CONFIG_USER_ONLY)
7442 , cpu_ppc_load_decr(env)
7443#endif
7444 );
077fc206 7445#endif
76a66253 7446 for (i = 0; i < 32; i++) {
3fc6c082
FB
7447 if ((i & (RGPL - 1)) == 0)
7448 cpu_fprintf(f, "GPR%02d", i);
6b542af7 7449 cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
3fc6c082 7450 if ((i & (RGPL - 1)) == (RGPL - 1))
7fe48483 7451 cpu_fprintf(f, "\n");
76a66253 7452 }
3fc6c082 7453 cpu_fprintf(f, "CR ");
76a66253 7454 for (i = 0; i < 8; i++)
7fe48483
FB
7455 cpu_fprintf(f, "%01x", env->crf[i]);
7456 cpu_fprintf(f, " [");
76a66253
JM
7457 for (i = 0; i < 8; i++) {
7458 char a = '-';
7459 if (env->crf[i] & 0x08)
7460 a = 'L';
7461 else if (env->crf[i] & 0x04)
7462 a = 'G';
7463 else if (env->crf[i] & 0x02)
7464 a = 'E';
7fe48483 7465 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
76a66253 7466 }
6b542af7 7467 cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
3fc6c082
FB
7468 for (i = 0; i < 32; i++) {
7469 if ((i & (RFPL - 1)) == 0)
7470 cpu_fprintf(f, "FPR%02d", i);
26a76461 7471 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
3fc6c082 7472 if ((i & (RFPL - 1)) == (RFPL - 1))
7fe48483 7473 cpu_fprintf(f, "\n");
79aceca5 7474 }
f2e63a42 7475#if !defined(CONFIG_USER_ONLY)
6b542af7 7476 cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
3fc6c082 7477 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
f2e63a42 7478#endif
79aceca5 7479
3fc6c082
FB
7480#undef RGPL
7481#undef RFPL
79aceca5
FB
7482}
7483
76a66253
JM
7484void cpu_dump_statistics (CPUState *env, FILE*f,
7485 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
7486 int flags)
7487{
7488#if defined(DO_PPC_STATISTICS)
7489 opc_handler_t **t1, **t2, **t3, *handler;
7490 int op1, op2, op3;
7491
7492 t1 = env->opcodes;
7493 for (op1 = 0; op1 < 64; op1++) {
7494 handler = t1[op1];
7495 if (is_indirect_opcode(handler)) {
7496 t2 = ind_table(handler);
7497 for (op2 = 0; op2 < 32; op2++) {
7498 handler = t2[op2];
7499 if (is_indirect_opcode(handler)) {
7500 t3 = ind_table(handler);
7501 for (op3 = 0; op3 < 32; op3++) {
7502 handler = t3[op3];
7503 if (handler->count == 0)
7504 continue;
7505 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
7506 "%016llx %lld\n",
7507 op1, op2, op3, op1, (op3 << 5) | op2,
7508 handler->oname,
7509 handler->count, handler->count);
7510 }
7511 } else {
7512 if (handler->count == 0)
7513 continue;
7514 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
7515 "%016llx %lld\n",
7516 op1, op2, op1, op2, handler->oname,
7517 handler->count, handler->count);
7518 }
7519 }
7520 } else {
7521 if (handler->count == 0)
7522 continue;
7523 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
7524 op1, op1, handler->oname,
7525 handler->count, handler->count);
7526 }
7527 }
7528#endif
7529}
7530
9a64fbe4 7531/*****************************************************************************/
2cfc5f17
TS
7532static always_inline void gen_intermediate_code_internal (CPUState *env,
7533 TranslationBlock *tb,
7534 int search_pc)
79aceca5 7535{
9fddaa0c 7536 DisasContext ctx, *ctxp = &ctx;
79aceca5 7537 opc_handler_t **table, *handler;
0fa85d43 7538 target_ulong pc_start;
79aceca5 7539 uint16_t *gen_opc_end;
056401ea 7540 int supervisor, little_endian;
a1d1bb31 7541 CPUBreakpoint *bp;
79aceca5 7542 int j, lj = -1;
2e70f6ef
PB
7543 int num_insns;
7544 int max_insns;
79aceca5
FB
7545
7546 pc_start = tb->pc;
79aceca5 7547 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
7c58044c
JM
7548#if defined(OPTIMIZE_FPRF_UPDATE)
7549 gen_fprf_ptr = gen_fprf_buf;
7550#endif
046d6672 7551 ctx.nip = pc_start;
79aceca5 7552 ctx.tb = tb;
e1833e1f 7553 ctx.exception = POWERPC_EXCP_NONE;
3fc6c082 7554 ctx.spr_cb = env->spr_cb;
6ebbf390
JM
7555 supervisor = env->mmu_idx;
7556#if !defined(CONFIG_USER_ONLY)
2857068e 7557 ctx.supervisor = supervisor;
d9bce9d9 7558#endif
056401ea 7559 little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
d9bce9d9
JM
7560#if defined(TARGET_PPC64)
7561 ctx.sf_mode = msr_sf;
056401ea 7562 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
2857068e 7563#else
056401ea 7564 ctx.mem_idx = (supervisor << 1) | little_endian;
9a64fbe4 7565#endif
d63001d1 7566 ctx.dcache_line_size = env->dcache_line_size;
3cc62370 7567 ctx.fpu_enabled = msr_fp;
a9d9eb8f 7568 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
d26bfc9a
JM
7569 ctx.spe_enabled = msr_spe;
7570 else
7571 ctx.spe_enabled = 0;
a9d9eb8f
JM
7572 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
7573 ctx.altivec_enabled = msr_vr;
7574 else
7575 ctx.altivec_enabled = 0;
d26bfc9a 7576 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
8cbcb4fa 7577 ctx.singlestep_enabled = CPU_SINGLE_STEP;
d26bfc9a 7578 else
8cbcb4fa 7579 ctx.singlestep_enabled = 0;
d26bfc9a 7580 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
8cbcb4fa
AJ
7581 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
7582 if (unlikely(env->singlestep_enabled))
7583 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
3fc6c082 7584#if defined (DO_SINGLE_STEP) && 0
9a64fbe4
FB
7585 /* Single step trace mode */
7586 msr_se = 1;
7587#endif
2e70f6ef
PB
7588 num_insns = 0;
7589 max_insns = tb->cflags & CF_COUNT_MASK;
7590 if (max_insns == 0)
7591 max_insns = CF_COUNT_MASK;
7592
7593 gen_icount_start();
9a64fbe4 7594 /* Set env in case of segfault during code fetch */
e1833e1f 7595 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
c0ce998e
AL
7596 if (unlikely(!TAILQ_EMPTY(&env->breakpoints))) {
7597 TAILQ_FOREACH(bp, &env->breakpoints, entry) {
a1d1bb31 7598 if (bp->pc == ctx.nip) {
5fafdf24 7599 gen_update_nip(&ctx, ctx.nip);
64adab3f 7600 gen_helper_raise_debug();
ea4e754f
FB
7601 break;
7602 }
7603 }
7604 }
76a66253 7605 if (unlikely(search_pc)) {
79aceca5
FB
7606 j = gen_opc_ptr - gen_opc_buf;
7607 if (lj < j) {
7608 lj++;
7609 while (lj < j)
7610 gen_opc_instr_start[lj++] = 0;
046d6672 7611 gen_opc_pc[lj] = ctx.nip;
79aceca5 7612 gen_opc_instr_start[lj] = 1;
2e70f6ef 7613 gen_opc_icount[lj] = num_insns;
79aceca5
FB
7614 }
7615 }
9fddaa0c
FB
7616#if defined PPC_DEBUG_DISAS
7617 if (loglevel & CPU_LOG_TB_IN_ASM) {
79aceca5 7618 fprintf(logfile, "----------------\n");
1b9eb036 7619 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
0411a972 7620 ctx.nip, supervisor, (int)msr_ir);
9a64fbe4
FB
7621 }
7622#endif
2e70f6ef
PB
7623 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
7624 gen_io_start();
056401ea
JM
7625 if (unlikely(little_endian)) {
7626 ctx.opcode = bswap32(ldl_code(ctx.nip));
7627 } else {
7628 ctx.opcode = ldl_code(ctx.nip);
111bfab3 7629 }
9fddaa0c
FB
7630#if defined PPC_DEBUG_DISAS
7631 if (loglevel & CPU_LOG_TB_IN_ASM) {
111bfab3 7632 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
9a64fbe4 7633 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
056401ea 7634 opc3(ctx.opcode), little_endian ? "little" : "big");
79aceca5
FB
7635 }
7636#endif
046d6672 7637 ctx.nip += 4;
3fc6c082 7638 table = env->opcodes;
2e70f6ef 7639 num_insns++;
79aceca5
FB
7640 handler = table[opc1(ctx.opcode)];
7641 if (is_indirect_opcode(handler)) {
7642 table = ind_table(handler);
7643 handler = table[opc2(ctx.opcode)];
7644 if (is_indirect_opcode(handler)) {
7645 table = ind_table(handler);
7646 handler = table[opc3(ctx.opcode)];
7647 }
7648 }
7649 /* Is opcode *REALLY* valid ? */
76a66253 7650 if (unlikely(handler->handler == &gen_invalid)) {
4a057712 7651 if (loglevel != 0) {
76a66253 7652 fprintf(logfile, "invalid/unsupported opcode: "
6b542af7 7653 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
76a66253 7654 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7655 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa
FB
7656 } else {
7657 printf("invalid/unsupported opcode: "
6b542af7 7658 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
4b3686fa 7659 opc1(ctx.opcode), opc2(ctx.opcode),
0411a972 7660 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
4b3686fa 7661 }
76a66253
JM
7662 } else {
7663 if (unlikely((ctx.opcode & handler->inval) != 0)) {
4a057712 7664 if (loglevel != 0) {
79aceca5 7665 fprintf(logfile, "invalid bits: %08x for opcode: "
6b542af7 7666 "%02x - %02x - %02x (%08x) " ADDRX "\n",
79aceca5
FB
7667 ctx.opcode & handler->inval, opc1(ctx.opcode),
7668 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7669 ctx.opcode, ctx.nip - 4);
9a64fbe4
FB
7670 } else {
7671 printf("invalid bits: %08x for opcode: "
6b542af7 7672 "%02x - %02x - %02x (%08x) " ADDRX "\n",
76a66253
JM
7673 ctx.opcode & handler->inval, opc1(ctx.opcode),
7674 opc2(ctx.opcode), opc3(ctx.opcode),
046d6672 7675 ctx.opcode, ctx.nip - 4);
76a66253 7676 }
e1833e1f 7677 GEN_EXCP_INVAL(ctxp);
4b3686fa 7678 break;
79aceca5 7679 }
79aceca5 7680 }
4b3686fa 7681 (*(handler->handler))(&ctx);
76a66253
JM
7682#if defined(DO_PPC_STATISTICS)
7683 handler->count++;
7684#endif
9a64fbe4 7685 /* Check trace mode exceptions */
8cbcb4fa
AJ
7686 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
7687 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
7688 ctx.exception != POWERPC_SYSCALL &&
7689 ctx.exception != POWERPC_EXCP_TRAP &&
7690 ctx.exception != POWERPC_EXCP_BRANCH)) {
e1833e1f 7691 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
d26bfc9a 7692 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
2e70f6ef
PB
7693 (env->singlestep_enabled) ||
7694 num_insns >= max_insns)) {
d26bfc9a
JM
7695 /* if we reach a page boundary or are single stepping, stop
7696 * generation
7697 */
8dd4983c 7698 break;
76a66253 7699 }
3fc6c082
FB
7700#if defined (DO_SINGLE_STEP)
7701 break;
7702#endif
7703 }
2e70f6ef
PB
7704 if (tb->cflags & CF_LAST_IO)
7705 gen_io_end();
e1833e1f 7706 if (ctx.exception == POWERPC_EXCP_NONE) {
c1942362 7707 gen_goto_tb(&ctx, 0, ctx.nip);
e1833e1f 7708 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
8cbcb4fa
AJ
7709 if (unlikely(env->singlestep_enabled)) {
7710 gen_update_nip(&ctx, ctx.nip);
64adab3f 7711 gen_helper_raise_debug();
8cbcb4fa 7712 }
76a66253 7713 /* Generate the return instruction */
57fec1fe 7714 tcg_gen_exit_tb(0);
9a64fbe4 7715 }
2e70f6ef 7716 gen_icount_end(tb, num_insns);
79aceca5 7717 *gen_opc_ptr = INDEX_op_end;
76a66253 7718 if (unlikely(search_pc)) {
9a64fbe4
FB
7719 j = gen_opc_ptr - gen_opc_buf;
7720 lj++;
7721 while (lj <= j)
7722 gen_opc_instr_start[lj++] = 0;
9a64fbe4 7723 } else {
046d6672 7724 tb->size = ctx.nip - pc_start;
2e70f6ef 7725 tb->icount = num_insns;
9a64fbe4 7726 }
d9bce9d9 7727#if defined(DEBUG_DISAS)
9fddaa0c 7728 if (loglevel & CPU_LOG_TB_CPU) {
9a64fbe4 7729 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
7fe48483 7730 cpu_dump_state(env, logfile, fprintf, 0);
9fddaa0c
FB
7731 }
7732 if (loglevel & CPU_LOG_TB_IN_ASM) {
76a66253 7733 int flags;
237c0af0 7734 flags = env->bfd_mach;
056401ea 7735 flags |= little_endian << 16;
0fa85d43 7736 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
76a66253 7737 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
79aceca5 7738 fprintf(logfile, "\n");
9fddaa0c 7739 }
79aceca5 7740#endif
79aceca5
FB
7741}
7742
2cfc5f17 7743void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
79aceca5 7744{
2cfc5f17 7745 gen_intermediate_code_internal(env, tb, 0);
79aceca5
FB
7746}
7747
2cfc5f17 7748void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
79aceca5 7749{
2cfc5f17 7750 gen_intermediate_code_internal(env, tb, 1);
79aceca5 7751}
d2856f1a
AJ
7752
7753void gen_pc_load(CPUState *env, TranslationBlock *tb,
7754 unsigned long searched_pc, int pc_pos, void *puc)
7755{
d2856f1a 7756 env->nip = gen_opc_pc[pc_pos];
d2856f1a 7757}