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