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