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