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