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