]> git.proxmox.com Git - qemu.git/blame_incremental - target-ppc/translate.c
alpha: add tests
[qemu.git] / target-ppc / translate.c
... / ...
CommitLineData
1/*
2 * PowerPC emulation for qemu: main translation routines.
3 *
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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 */
20#include <stdarg.h>
21#include <stdlib.h>
22#include <stdio.h>
23#include <string.h>
24#include <inttypes.h>
25
26#include "cpu.h"
27#include "exec-all.h"
28#include "disas.h"
29#include "helper.h"
30#include "tcg-op.h"
31#include "qemu-common.h"
32
33#define CPU_SINGLE_STEP 0x1
34#define CPU_BRANCH_STEP 0x2
35#define GDBSTUB_SINGLE_STEP 0x4
36
37/* Include definitions for instructions classes and implementations flags */
38//#define DO_SINGLE_STEP
39//#define PPC_DEBUG_DISAS
40//#define DEBUG_MEMORY_ACCESSES
41//#define DO_PPC_STATISTICS
42//#define OPTIMIZE_FPRF_UPDATE
43
44/*****************************************************************************/
45/* Code translation helpers */
46
47/* global register indexes */
48static TCGv cpu_env;
49static char cpu_reg_names[10*3 + 22*4 /* GPR */
50#if !defined(TARGET_PPC64)
51 + 10*4 + 22*5 /* SPE GPRh */
52#endif
53 + 10*4 + 22*5 /* FPR */
54 + 2*(10*6 + 22*7) /* AVRh, AVRl */
55 + 8*5 /* CRF */];
56static TCGv cpu_gpr[32];
57#if !defined(TARGET_PPC64)
58static TCGv cpu_gprh[32];
59#endif
60static TCGv cpu_fpr[32];
61static TCGv cpu_avrh[32], cpu_avrl[32];
62static TCGv cpu_crf[8];
63static TCGv cpu_nip;
64
65/* dyngen register indexes */
66static TCGv cpu_T[3];
67#if defined(TARGET_PPC64)
68#define cpu_T64 cpu_T
69#else
70static TCGv cpu_T64[3];
71#endif
72static TCGv cpu_FT[3];
73static TCGv cpu_AVRh[3], cpu_AVRl[3];
74
75#include "gen-icount.h"
76
77void ppc_translate_init(void)
78{
79 int i;
80 char* p;
81 static int done_init = 0;
82
83 if (done_init)
84 return;
85
86 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
87#if TARGET_LONG_BITS > HOST_LONG_BITS
88 cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
89 TCG_AREG0, offsetof(CPUState, t0), "T0");
90 cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
91 TCG_AREG0, offsetof(CPUState, t1), "T1");
92 cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
93 TCG_AREG0, offsetof(CPUState, t2), "T2");
94#else
95 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
96 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
97 cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
98#endif
99#if !defined(TARGET_PPC64)
100 cpu_T64[0] = tcg_global_mem_new(TCG_TYPE_I64,
101 TCG_AREG0, offsetof(CPUState, t0_64),
102 "T0_64");
103 cpu_T64[1] = tcg_global_mem_new(TCG_TYPE_I64,
104 TCG_AREG0, offsetof(CPUState, t1_64),
105 "T1_64");
106 cpu_T64[2] = tcg_global_mem_new(TCG_TYPE_I64,
107 TCG_AREG0, offsetof(CPUState, t2_64),
108 "T2_64");
109#endif
110
111 cpu_FT[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
112 offsetof(CPUState, ft0), "FT0");
113 cpu_FT[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
114 offsetof(CPUState, ft1), "FT1");
115 cpu_FT[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
116 offsetof(CPUState, ft2), "FT2");
117
118 cpu_AVRh[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
119 offsetof(CPUState, avr0.u64[0]), "AVR0H");
120 cpu_AVRl[0] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
121 offsetof(CPUState, avr0.u64[1]), "AVR0L");
122 cpu_AVRh[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
123 offsetof(CPUState, avr1.u64[0]), "AVR1H");
124 cpu_AVRl[1] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
125 offsetof(CPUState, avr1.u64[1]), "AVR1L");
126 cpu_AVRh[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
127 offsetof(CPUState, avr2.u64[0]), "AVR2H");
128 cpu_AVRl[2] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
129 offsetof(CPUState, avr2.u64[1]), "AVR2L");
130
131 p = cpu_reg_names;
132
133 for (i = 0; i < 8; i++) {
134 sprintf(p, "crf%d", i);
135 cpu_crf[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
136 offsetof(CPUState, crf[i]), p);
137 p += 5;
138 }
139
140 for (i = 0; i < 32; i++) {
141 sprintf(p, "r%d", i);
142 cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
143 offsetof(CPUState, gpr[i]), p);
144 p += (i < 10) ? 3 : 4;
145#if !defined(TARGET_PPC64)
146 sprintf(p, "r%dH", i);
147 cpu_gprh[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
148 offsetof(CPUState, gprh[i]), p);
149 p += (i < 10) ? 4 : 5;
150#endif
151
152 sprintf(p, "fp%d", i);
153 cpu_fpr[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
154 offsetof(CPUState, fpr[i]), p);
155 p += (i < 10) ? 4 : 5;
156
157 sprintf(p, "avr%dH", i);
158 cpu_avrh[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
159 offsetof(CPUState, avr[i].u64[0]), p);
160 p += (i < 10) ? 6 : 7;
161
162 sprintf(p, "avr%dL", i);
163 cpu_avrl[i] = tcg_global_mem_new(TCG_TYPE_I64, TCG_AREG0,
164 offsetof(CPUState, avr[i].u64[1]), p);
165 p += (i < 10) ? 6 : 7;
166 }
167
168 cpu_nip = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
169 offsetof(CPUState, nip), "nip");
170
171 /* register helpers */
172#undef DEF_HELPER
173#define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
174#include "helper.h"
175
176 done_init = 1;
177}
178
179#if defined(OPTIMIZE_FPRF_UPDATE)
180static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
181static uint16_t **gen_fprf_ptr;
182#endif
183
184/* internal defines */
185typedef struct DisasContext {
186 struct TranslationBlock *tb;
187 target_ulong nip;
188 uint32_t opcode;
189 uint32_t exception;
190 /* Routine used to access memory */
191 int mem_idx;
192 /* Translation flags */
193#if !defined(CONFIG_USER_ONLY)
194 int supervisor;
195#endif
196#if defined(TARGET_PPC64)
197 int sf_mode;
198#endif
199 int fpu_enabled;
200 int altivec_enabled;
201 int spe_enabled;
202 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
203 int singlestep_enabled;
204 int dcache_line_size;
205} DisasContext;
206
207struct opc_handler_t {
208 /* invalid bits */
209 uint32_t inval;
210 /* instruction type */
211 uint64_t type;
212 /* handler */
213 void (*handler)(DisasContext *ctx);
214#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
215 const unsigned char *oname;
216#endif
217#if defined(DO_PPC_STATISTICS)
218 uint64_t count;
219#endif
220};
221
222static always_inline void gen_set_Rc0 (DisasContext *ctx)
223{
224#if defined(TARGET_PPC64)
225 if (ctx->sf_mode)
226 gen_op_cmpi_64(0);
227 else
228#endif
229 gen_op_cmpi(0);
230 gen_op_set_Rc0();
231}
232
233static always_inline void gen_reset_fpstatus (void)
234{
235#ifdef CONFIG_SOFTFLOAT
236 gen_op_reset_fpstatus();
237#endif
238}
239
240static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
241{
242 if (set_fprf != 0) {
243 /* This case might be optimized later */
244#if defined(OPTIMIZE_FPRF_UPDATE)
245 *gen_fprf_ptr++ = gen_opc_ptr;
246#endif
247 gen_op_compute_fprf(1);
248 if (unlikely(set_rc))
249 tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
250 gen_op_float_check_status();
251 } else if (unlikely(set_rc)) {
252 /* We always need to compute fpcc */
253 gen_op_compute_fprf(0);
254 tcg_gen_andi_i32(cpu_crf[1], cpu_T[0], 0xf);
255 if (set_fprf)
256 gen_op_float_check_status();
257 }
258}
259
260static always_inline void gen_optimize_fprf (void)
261{
262#if defined(OPTIMIZE_FPRF_UPDATE)
263 uint16_t **ptr;
264
265 for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
266 *ptr = INDEX_op_nop1;
267 gen_fprf_ptr = gen_fprf_buf;
268#endif
269}
270
271static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
272{
273#if defined(TARGET_PPC64)
274 if (ctx->sf_mode)
275 tcg_gen_movi_tl(cpu_nip, nip);
276 else
277#endif
278 tcg_gen_movi_tl(cpu_nip, (uint32_t)nip);
279}
280
281#define GEN_EXCP(ctx, excp, error) \
282do { \
283 if ((ctx)->exception == POWERPC_EXCP_NONE) { \
284 gen_update_nip(ctx, (ctx)->nip); \
285 } \
286 gen_op_raise_exception_err((excp), (error)); \
287 ctx->exception = (excp); \
288} while (0)
289
290#define GEN_EXCP_INVAL(ctx) \
291GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
292 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
293
294#define GEN_EXCP_PRIVOPC(ctx) \
295GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
296 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
297
298#define GEN_EXCP_PRIVREG(ctx) \
299GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
300 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
301
302#define GEN_EXCP_NO_FP(ctx) \
303GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
304
305#define GEN_EXCP_NO_AP(ctx) \
306GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
307
308#define GEN_EXCP_NO_VR(ctx) \
309GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
310
311/* Stop translation */
312static always_inline void GEN_STOP (DisasContext *ctx)
313{
314 gen_update_nip(ctx, ctx->nip);
315 ctx->exception = POWERPC_EXCP_STOP;
316}
317
318/* No need to update nip here, as execution flow will change */
319static always_inline void GEN_SYNC (DisasContext *ctx)
320{
321 ctx->exception = POWERPC_EXCP_SYNC;
322}
323
324#define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
325static void gen_##name (DisasContext *ctx); \
326GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
327static void gen_##name (DisasContext *ctx)
328
329#define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
330static void gen_##name (DisasContext *ctx); \
331GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type); \
332static void gen_##name (DisasContext *ctx)
333
334typedef struct opcode_t {
335 unsigned char opc1, opc2, opc3;
336#if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
337 unsigned char pad[5];
338#else
339 unsigned char pad[1];
340#endif
341 opc_handler_t handler;
342 const unsigned char *oname;
343} opcode_t;
344
345/*****************************************************************************/
346/*** Instruction decoding ***/
347#define EXTRACT_HELPER(name, shift, nb) \
348static always_inline uint32_t name (uint32_t opcode) \
349{ \
350 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
351}
352
353#define EXTRACT_SHELPER(name, shift, nb) \
354static always_inline int32_t name (uint32_t opcode) \
355{ \
356 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
357}
358
359/* Opcode part 1 */
360EXTRACT_HELPER(opc1, 26, 6);
361/* Opcode part 2 */
362EXTRACT_HELPER(opc2, 1, 5);
363/* Opcode part 3 */
364EXTRACT_HELPER(opc3, 6, 5);
365/* Update Cr0 flags */
366EXTRACT_HELPER(Rc, 0, 1);
367/* Destination */
368EXTRACT_HELPER(rD, 21, 5);
369/* Source */
370EXTRACT_HELPER(rS, 21, 5);
371/* First operand */
372EXTRACT_HELPER(rA, 16, 5);
373/* Second operand */
374EXTRACT_HELPER(rB, 11, 5);
375/* Third operand */
376EXTRACT_HELPER(rC, 6, 5);
377/*** Get CRn ***/
378EXTRACT_HELPER(crfD, 23, 3);
379EXTRACT_HELPER(crfS, 18, 3);
380EXTRACT_HELPER(crbD, 21, 5);
381EXTRACT_HELPER(crbA, 16, 5);
382EXTRACT_HELPER(crbB, 11, 5);
383/* SPR / TBL */
384EXTRACT_HELPER(_SPR, 11, 10);
385static always_inline uint32_t SPR (uint32_t opcode)
386{
387 uint32_t sprn = _SPR(opcode);
388
389 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
390}
391/*** Get constants ***/
392EXTRACT_HELPER(IMM, 12, 8);
393/* 16 bits signed immediate value */
394EXTRACT_SHELPER(SIMM, 0, 16);
395/* 16 bits unsigned immediate value */
396EXTRACT_HELPER(UIMM, 0, 16);
397/* Bit count */
398EXTRACT_HELPER(NB, 11, 5);
399/* Shift count */
400EXTRACT_HELPER(SH, 11, 5);
401/* Mask start */
402EXTRACT_HELPER(MB, 6, 5);
403/* Mask end */
404EXTRACT_HELPER(ME, 1, 5);
405/* Trap operand */
406EXTRACT_HELPER(TO, 21, 5);
407
408EXTRACT_HELPER(CRM, 12, 8);
409EXTRACT_HELPER(FM, 17, 8);
410EXTRACT_HELPER(SR, 16, 4);
411EXTRACT_HELPER(FPIMM, 12, 4);
412
413/*** Jump target decoding ***/
414/* Displacement */
415EXTRACT_SHELPER(d, 0, 16);
416/* Immediate address */
417static always_inline target_ulong LI (uint32_t opcode)
418{
419 return (opcode >> 0) & 0x03FFFFFC;
420}
421
422static always_inline uint32_t BD (uint32_t opcode)
423{
424 return (opcode >> 0) & 0xFFFC;
425}
426
427EXTRACT_HELPER(BO, 21, 5);
428EXTRACT_HELPER(BI, 16, 5);
429/* Absolute/relative address */
430EXTRACT_HELPER(AA, 1, 1);
431/* Link */
432EXTRACT_HELPER(LK, 0, 1);
433
434/* Create a mask between <start> and <end> bits */
435static always_inline target_ulong MASK (uint32_t start, uint32_t end)
436{
437 target_ulong ret;
438
439#if defined(TARGET_PPC64)
440 if (likely(start == 0)) {
441 ret = UINT64_MAX << (63 - end);
442 } else if (likely(end == 63)) {
443 ret = UINT64_MAX >> start;
444 }
445#else
446 if (likely(start == 0)) {
447 ret = UINT32_MAX << (31 - end);
448 } else if (likely(end == 31)) {
449 ret = UINT32_MAX >> start;
450 }
451#endif
452 else {
453 ret = (((target_ulong)(-1ULL)) >> (start)) ^
454 (((target_ulong)(-1ULL) >> (end)) >> 1);
455 if (unlikely(start > end))
456 return ~ret;
457 }
458
459 return ret;
460}
461
462/*****************************************************************************/
463/* PowerPC Instructions types definitions */
464enum {
465 PPC_NONE = 0x0000000000000000ULL,
466 /* PowerPC base instructions set */
467 PPC_INSNS_BASE = 0x0000000000000001ULL,
468 /* integer operations instructions */
469#define PPC_INTEGER PPC_INSNS_BASE
470 /* flow control instructions */
471#define PPC_FLOW PPC_INSNS_BASE
472 /* virtual memory instructions */
473#define PPC_MEM PPC_INSNS_BASE
474 /* ld/st with reservation instructions */
475#define PPC_RES PPC_INSNS_BASE
476 /* spr/msr access instructions */
477#define PPC_MISC PPC_INSNS_BASE
478 /* Deprecated instruction sets */
479 /* Original POWER instruction set */
480 PPC_POWER = 0x0000000000000002ULL,
481 /* POWER2 instruction set extension */
482 PPC_POWER2 = 0x0000000000000004ULL,
483 /* Power RTC support */
484 PPC_POWER_RTC = 0x0000000000000008ULL,
485 /* Power-to-PowerPC bridge (601) */
486 PPC_POWER_BR = 0x0000000000000010ULL,
487 /* 64 bits PowerPC instruction set */
488 PPC_64B = 0x0000000000000020ULL,
489 /* New 64 bits extensions (PowerPC 2.0x) */
490 PPC_64BX = 0x0000000000000040ULL,
491 /* 64 bits hypervisor extensions */
492 PPC_64H = 0x0000000000000080ULL,
493 /* New wait instruction (PowerPC 2.0x) */
494 PPC_WAIT = 0x0000000000000100ULL,
495 /* Time base mftb instruction */
496 PPC_MFTB = 0x0000000000000200ULL,
497
498 /* Fixed-point unit extensions */
499 /* PowerPC 602 specific */
500 PPC_602_SPEC = 0x0000000000000400ULL,
501 /* isel instruction */
502 PPC_ISEL = 0x0000000000000800ULL,
503 /* popcntb instruction */
504 PPC_POPCNTB = 0x0000000000001000ULL,
505 /* string load / store */
506 PPC_STRING = 0x0000000000002000ULL,
507
508 /* Floating-point unit extensions */
509 /* Optional floating point instructions */
510 PPC_FLOAT = 0x0000000000010000ULL,
511 /* New floating-point extensions (PowerPC 2.0x) */
512 PPC_FLOAT_EXT = 0x0000000000020000ULL,
513 PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
514 PPC_FLOAT_FRES = 0x0000000000080000ULL,
515 PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
516 PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
517 PPC_FLOAT_FSEL = 0x0000000000400000ULL,
518 PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
519
520 /* Vector/SIMD extensions */
521 /* Altivec support */
522 PPC_ALTIVEC = 0x0000000001000000ULL,
523 /* PowerPC 2.03 SPE extension */
524 PPC_SPE = 0x0000000002000000ULL,
525 /* PowerPC 2.03 SPE floating-point extension */
526 PPC_SPEFPU = 0x0000000004000000ULL,
527
528 /* Optional memory control instructions */
529 PPC_MEM_TLBIA = 0x0000000010000000ULL,
530 PPC_MEM_TLBIE = 0x0000000020000000ULL,
531 PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
532 /* sync instruction */
533 PPC_MEM_SYNC = 0x0000000080000000ULL,
534 /* eieio instruction */
535 PPC_MEM_EIEIO = 0x0000000100000000ULL,
536
537 /* Cache control instructions */
538 PPC_CACHE = 0x0000000200000000ULL,
539 /* icbi instruction */
540 PPC_CACHE_ICBI = 0x0000000400000000ULL,
541 /* dcbz instruction with fixed cache line size */
542 PPC_CACHE_DCBZ = 0x0000000800000000ULL,
543 /* dcbz instruction with tunable cache line size */
544 PPC_CACHE_DCBZT = 0x0000001000000000ULL,
545 /* dcba instruction */
546 PPC_CACHE_DCBA = 0x0000002000000000ULL,
547 /* Freescale cache locking instructions */
548 PPC_CACHE_LOCK = 0x0000004000000000ULL,
549
550 /* MMU related extensions */
551 /* external control instructions */
552 PPC_EXTERN = 0x0000010000000000ULL,
553 /* segment register access instructions */
554 PPC_SEGMENT = 0x0000020000000000ULL,
555 /* PowerPC 6xx TLB management instructions */
556 PPC_6xx_TLB = 0x0000040000000000ULL,
557 /* PowerPC 74xx TLB management instructions */
558 PPC_74xx_TLB = 0x0000080000000000ULL,
559 /* PowerPC 40x TLB management instructions */
560 PPC_40x_TLB = 0x0000100000000000ULL,
561 /* segment register access instructions for PowerPC 64 "bridge" */
562 PPC_SEGMENT_64B = 0x0000200000000000ULL,
563 /* SLB management */
564 PPC_SLBI = 0x0000400000000000ULL,
565
566 /* Embedded PowerPC dedicated instructions */
567 PPC_WRTEE = 0x0001000000000000ULL,
568 /* PowerPC 40x exception model */
569 PPC_40x_EXCP = 0x0002000000000000ULL,
570 /* PowerPC 405 Mac instructions */
571 PPC_405_MAC = 0x0004000000000000ULL,
572 /* PowerPC 440 specific instructions */
573 PPC_440_SPEC = 0x0008000000000000ULL,
574 /* BookE (embedded) PowerPC specification */
575 PPC_BOOKE = 0x0010000000000000ULL,
576 /* mfapidi instruction */
577 PPC_MFAPIDI = 0x0020000000000000ULL,
578 /* tlbiva instruction */
579 PPC_TLBIVA = 0x0040000000000000ULL,
580 /* tlbivax instruction */
581 PPC_TLBIVAX = 0x0080000000000000ULL,
582 /* PowerPC 4xx dedicated instructions */
583 PPC_4xx_COMMON = 0x0100000000000000ULL,
584 /* PowerPC 40x ibct instructions */
585 PPC_40x_ICBT = 0x0200000000000000ULL,
586 /* rfmci is not implemented in all BookE PowerPC */
587 PPC_RFMCI = 0x0400000000000000ULL,
588 /* rfdi instruction */
589 PPC_RFDI = 0x0800000000000000ULL,
590 /* DCR accesses */
591 PPC_DCR = 0x1000000000000000ULL,
592 /* DCR extended accesse */
593 PPC_DCRX = 0x2000000000000000ULL,
594 /* user-mode DCR access, implemented in PowerPC 460 */
595 PPC_DCRUX = 0x4000000000000000ULL,
596};
597
598/*****************************************************************************/
599/* PowerPC instructions table */
600#if HOST_LONG_BITS == 64
601#define OPC_ALIGN 8
602#else
603#define OPC_ALIGN 4
604#endif
605#if defined(__APPLE__)
606#define OPCODES_SECTION \
607 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
608#else
609#define OPCODES_SECTION \
610 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
611#endif
612
613#if defined(DO_PPC_STATISTICS)
614#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
615OPCODES_SECTION opcode_t opc_##name = { \
616 .opc1 = op1, \
617 .opc2 = op2, \
618 .opc3 = op3, \
619 .pad = { 0, }, \
620 .handler = { \
621 .inval = invl, \
622 .type = _typ, \
623 .handler = &gen_##name, \
624 .oname = stringify(name), \
625 }, \
626 .oname = stringify(name), \
627}
628#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
629OPCODES_SECTION opcode_t opc_##name = { \
630 .opc1 = op1, \
631 .opc2 = op2, \
632 .opc3 = op3, \
633 .pad = { 0, }, \
634 .handler = { \
635 .inval = invl, \
636 .type = _typ, \
637 .handler = &gen_##name, \
638 .oname = onam, \
639 }, \
640 .oname = onam, \
641}
642#else
643#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
644OPCODES_SECTION opcode_t opc_##name = { \
645 .opc1 = op1, \
646 .opc2 = op2, \
647 .opc3 = op3, \
648 .pad = { 0, }, \
649 .handler = { \
650 .inval = invl, \
651 .type = _typ, \
652 .handler = &gen_##name, \
653 }, \
654 .oname = stringify(name), \
655}
656#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
657OPCODES_SECTION opcode_t opc_##name = { \
658 .opc1 = op1, \
659 .opc2 = op2, \
660 .opc3 = op3, \
661 .pad = { 0, }, \
662 .handler = { \
663 .inval = invl, \
664 .type = _typ, \
665 .handler = &gen_##name, \
666 }, \
667 .oname = onam, \
668}
669#endif
670
671#define GEN_OPCODE_MARK(name) \
672OPCODES_SECTION opcode_t opc_##name = { \
673 .opc1 = 0xFF, \
674 .opc2 = 0xFF, \
675 .opc3 = 0xFF, \
676 .pad = { 0, }, \
677 .handler = { \
678 .inval = 0x00000000, \
679 .type = 0x00, \
680 .handler = NULL, \
681 }, \
682 .oname = stringify(name), \
683}
684
685/* Start opcode list */
686GEN_OPCODE_MARK(start);
687
688/* Invalid instruction */
689GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
690{
691 GEN_EXCP_INVAL(ctx);
692}
693
694static opc_handler_t invalid_handler = {
695 .inval = 0xFFFFFFFF,
696 .type = PPC_NONE,
697 .handler = gen_invalid,
698};
699
700/*** Integer arithmetic ***/
701#define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
702GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
703{ \
704 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
705 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
706 gen_op_##name(); \
707 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
708 if (unlikely(Rc(ctx->opcode) != 0)) \
709 gen_set_Rc0(ctx); \
710}
711
712#define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
713GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
714{ \
715 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
716 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
717 gen_op_##name(); \
718 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
719 if (unlikely(Rc(ctx->opcode) != 0)) \
720 gen_set_Rc0(ctx); \
721}
722
723#define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
724GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
725{ \
726 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
727 gen_op_##name(); \
728 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
729 if (unlikely(Rc(ctx->opcode) != 0)) \
730 gen_set_Rc0(ctx); \
731}
732#define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
733GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
734{ \
735 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
736 gen_op_##name(); \
737 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
738 if (unlikely(Rc(ctx->opcode) != 0)) \
739 gen_set_Rc0(ctx); \
740}
741
742/* Two operands arithmetic functions */
743#define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
744__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
745__GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
746
747/* Two operands arithmetic functions with no overflow allowed */
748#define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
749__GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
750
751/* One operand arithmetic functions */
752#define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
753__GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
754__GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
755
756#if defined(TARGET_PPC64)
757#define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
758GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
759{ \
760 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
761 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
762 if (ctx->sf_mode) \
763 gen_op_##name##_64(); \
764 else \
765 gen_op_##name(); \
766 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
767 if (unlikely(Rc(ctx->opcode) != 0)) \
768 gen_set_Rc0(ctx); \
769}
770
771#define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
772GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
773{ \
774 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
775 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
776 if (ctx->sf_mode) \
777 gen_op_##name##_64(); \
778 else \
779 gen_op_##name(); \
780 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
781 if (unlikely(Rc(ctx->opcode) != 0)) \
782 gen_set_Rc0(ctx); \
783}
784
785#define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
786GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
787{ \
788 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
789 if (ctx->sf_mode) \
790 gen_op_##name##_64(); \
791 else \
792 gen_op_##name(); \
793 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
794 if (unlikely(Rc(ctx->opcode) != 0)) \
795 gen_set_Rc0(ctx); \
796}
797#define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
798GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
799{ \
800 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
801 if (ctx->sf_mode) \
802 gen_op_##name##_64(); \
803 else \
804 gen_op_##name(); \
805 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
806 if (unlikely(Rc(ctx->opcode) != 0)) \
807 gen_set_Rc0(ctx); \
808}
809
810/* Two operands arithmetic functions */
811#define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
812__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
813__GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
814
815/* Two operands arithmetic functions with no overflow allowed */
816#define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
817__GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
818
819/* One operand arithmetic functions */
820#define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
821__GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
822__GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
823#else
824#define GEN_INT_ARITH2_64 GEN_INT_ARITH2
825#define GEN_INT_ARITHN_64 GEN_INT_ARITHN
826#define GEN_INT_ARITH1_64 GEN_INT_ARITH1
827#endif
828
829/* add add. addo addo. */
830static always_inline void gen_op_add (void)
831{
832 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
833}
834static always_inline void gen_op_addo (void)
835{
836 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
837 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
838 gen_op_check_addo();
839}
840#if defined(TARGET_PPC64)
841#define gen_op_add_64 gen_op_add
842static always_inline void gen_op_addo_64 (void)
843{
844 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
845 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
846 gen_op_check_addo_64();
847}
848#endif
849GEN_INT_ARITH2_64 (add, 0x1F, 0x0A, 0x08, PPC_INTEGER);
850/* addc addc. addco addco. */
851static always_inline void gen_op_addc (void)
852{
853 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
854 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
855 gen_op_check_addc();
856}
857static always_inline void gen_op_addco (void)
858{
859 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
860 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
861 gen_op_check_addc();
862 gen_op_check_addo();
863}
864#if defined(TARGET_PPC64)
865static always_inline void gen_op_addc_64 (void)
866{
867 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
868 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
869 gen_op_check_addc_64();
870}
871static always_inline void gen_op_addco_64 (void)
872{
873 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
874 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
875 gen_op_check_addc_64();
876 gen_op_check_addo_64();
877}
878#endif
879GEN_INT_ARITH2_64 (addc, 0x1F, 0x0A, 0x00, PPC_INTEGER);
880/* adde adde. addeo addeo. */
881static always_inline void gen_op_addeo (void)
882{
883 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
884 gen_op_adde();
885 gen_op_check_addo();
886}
887#if defined(TARGET_PPC64)
888static always_inline void gen_op_addeo_64 (void)
889{
890 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
891 gen_op_adde_64();
892 gen_op_check_addo_64();
893}
894#endif
895GEN_INT_ARITH2_64 (adde, 0x1F, 0x0A, 0x04, PPC_INTEGER);
896/* addme addme. addmeo addmeo. */
897static always_inline void gen_op_addme (void)
898{
899 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
900 gen_op_add_me();
901}
902#if defined(TARGET_PPC64)
903static always_inline void gen_op_addme_64 (void)
904{
905 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
906 gen_op_add_me_64();
907}
908#endif
909GEN_INT_ARITH1_64 (addme, 0x1F, 0x0A, 0x07, PPC_INTEGER);
910/* addze addze. addzeo addzeo. */
911static always_inline void gen_op_addze (void)
912{
913 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
914 gen_op_add_ze();
915 gen_op_check_addc();
916}
917static always_inline void gen_op_addzeo (void)
918{
919 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
920 gen_op_add_ze();
921 gen_op_check_addc();
922 gen_op_check_addo();
923}
924#if defined(TARGET_PPC64)
925static always_inline void gen_op_addze_64 (void)
926{
927 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
928 gen_op_add_ze();
929 gen_op_check_addc_64();
930}
931static always_inline void gen_op_addzeo_64 (void)
932{
933 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
934 gen_op_add_ze();
935 gen_op_check_addc_64();
936 gen_op_check_addo_64();
937}
938#endif
939GEN_INT_ARITH1_64 (addze, 0x1F, 0x0A, 0x06, PPC_INTEGER);
940/* divw divw. divwo divwo. */
941GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F, PPC_INTEGER);
942/* divwu divwu. divwuo divwuo. */
943GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E, PPC_INTEGER);
944/* mulhw mulhw. */
945GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02, PPC_INTEGER);
946/* mulhwu mulhwu. */
947GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
948/* mullw mullw. mullwo mullwo. */
949GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07, PPC_INTEGER);
950/* neg neg. nego nego. */
951GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
952/* subf subf. subfo subfo. */
953static always_inline void gen_op_subf (void)
954{
955 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
956}
957static always_inline void gen_op_subfo (void)
958{
959 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
960 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
961 gen_op_check_addo();
962}
963#if defined(TARGET_PPC64)
964#define gen_op_subf_64 gen_op_subf
965static always_inline void gen_op_subfo_64 (void)
966{
967 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
968 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
969 gen_op_check_addo_64();
970}
971#endif
972GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
973/* subfc subfc. subfco subfco. */
974static always_inline void gen_op_subfc (void)
975{
976 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
977 gen_op_check_subfc();
978}
979static always_inline void gen_op_subfco (void)
980{
981 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
982 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
983 gen_op_check_subfc();
984 gen_op_check_addo();
985}
986#if defined(TARGET_PPC64)
987static always_inline void gen_op_subfc_64 (void)
988{
989 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
990 gen_op_check_subfc_64();
991}
992static always_inline void gen_op_subfco_64 (void)
993{
994 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
995 tcg_gen_sub_tl(cpu_T[0], cpu_T[1], cpu_T[0]);
996 gen_op_check_subfc_64();
997 gen_op_check_addo_64();
998}
999#endif
1000GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
1001/* subfe subfe. subfeo subfeo. */
1002static always_inline void gen_op_subfeo (void)
1003{
1004 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
1005 gen_op_subfe();
1006 gen_op_check_addo();
1007}
1008#if defined(TARGET_PPC64)
1009#define gen_op_subfe_64 gen_op_subfe
1010static always_inline void gen_op_subfeo_64 (void)
1011{
1012 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
1013 gen_op_subfe_64();
1014 gen_op_check_addo_64();
1015}
1016#endif
1017GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
1018/* subfme subfme. subfmeo subfmeo. */
1019GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
1020/* subfze subfze. subfzeo subfzeo. */
1021GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
1022/* addi */
1023GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1024{
1025 target_long simm = SIMM(ctx->opcode);
1026
1027 if (rA(ctx->opcode) == 0) {
1028 /* li case */
1029 tcg_gen_movi_tl(cpu_T[0], simm);
1030 } else {
1031 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1032 if (likely(simm != 0))
1033 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm);
1034 }
1035 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1036}
1037/* addic */
1038GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1039{
1040 target_long simm = SIMM(ctx->opcode);
1041
1042 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1043 if (likely(simm != 0)) {
1044 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1045 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm);
1046#if defined(TARGET_PPC64)
1047 if (ctx->sf_mode)
1048 gen_op_check_addc_64();
1049 else
1050#endif
1051 gen_op_check_addc();
1052 } else {
1053 gen_op_clear_xer_ca();
1054 }
1055 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1056}
1057/* addic. */
1058GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1059{
1060 target_long simm = SIMM(ctx->opcode);
1061
1062 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1063 if (likely(simm != 0)) {
1064 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1065 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm);
1066#if defined(TARGET_PPC64)
1067 if (ctx->sf_mode)
1068 gen_op_check_addc_64();
1069 else
1070#endif
1071 gen_op_check_addc();
1072 } else {
1073 gen_op_clear_xer_ca();
1074 }
1075 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1076 gen_set_Rc0(ctx);
1077}
1078/* addis */
1079GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1080{
1081 target_long simm = SIMM(ctx->opcode);
1082
1083 if (rA(ctx->opcode) == 0) {
1084 /* lis case */
1085 tcg_gen_movi_tl(cpu_T[0], simm << 16);
1086 } else {
1087 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1088 if (likely(simm != 0))
1089 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm << 16);
1090 }
1091 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1092}
1093/* mulli */
1094GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1095{
1096 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1097 gen_op_mulli(SIMM(ctx->opcode));
1098 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1099}
1100/* subfic */
1101GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1102{
1103 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1104#if defined(TARGET_PPC64)
1105 if (ctx->sf_mode)
1106 gen_op_subfic_64(SIMM(ctx->opcode));
1107 else
1108#endif
1109 gen_op_subfic(SIMM(ctx->opcode));
1110 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1111}
1112
1113#if defined(TARGET_PPC64)
1114/* mulhd mulhd. */
1115GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_64B);
1116/* mulhdu mulhdu. */
1117GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
1118/* mulld mulld. mulldo mulldo. */
1119GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_64B);
1120/* divd divd. divdo divdo. */
1121GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_64B);
1122/* divdu divdu. divduo divduo. */
1123GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B);
1124#endif
1125
1126/*** Integer comparison ***/
1127#if defined(TARGET_PPC64)
1128#define GEN_CMP(name, opc, type) \
1129GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1130{ \
1131 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
1132 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1133 if (ctx->sf_mode && (ctx->opcode & 0x00200000)) \
1134 gen_op_##name##_64(); \
1135 else \
1136 gen_op_##name(); \
1137 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
1138}
1139#else
1140#define GEN_CMP(name, opc, type) \
1141GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1142{ \
1143 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
1144 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1145 gen_op_##name(); \
1146 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
1147}
1148#endif
1149
1150/* cmp */
1151GEN_CMP(cmp, 0x00, PPC_INTEGER);
1152/* cmpi */
1153GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1154{
1155 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1156#if defined(TARGET_PPC64)
1157 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1158 gen_op_cmpi_64(SIMM(ctx->opcode));
1159 else
1160#endif
1161 gen_op_cmpi(SIMM(ctx->opcode));
1162 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1163}
1164/* cmpl */
1165GEN_CMP(cmpl, 0x01, PPC_INTEGER);
1166/* cmpli */
1167GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1168{
1169 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1170#if defined(TARGET_PPC64)
1171 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1172 gen_op_cmpli_64(UIMM(ctx->opcode));
1173 else
1174#endif
1175 gen_op_cmpli(UIMM(ctx->opcode));
1176 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1177}
1178
1179/* isel (PowerPC 2.03 specification) */
1180GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
1181{
1182 uint32_t bi = rC(ctx->opcode);
1183 uint32_t mask;
1184
1185 if (rA(ctx->opcode) == 0) {
1186 tcg_gen_movi_tl(cpu_T[0], 0);
1187 } else {
1188 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1189 }
1190 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
1191 mask = 1 << (3 - (bi & 0x03));
1192 tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
1193 gen_op_test_true(mask);
1194 gen_op_isel();
1195 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1196}
1197
1198/*** Integer logical ***/
1199#define __GEN_LOGICAL2(name, opc2, opc3, type) \
1200GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
1201{ \
1202 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); \
1203 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1204 gen_op_##name(); \
1205 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
1206 if (unlikely(Rc(ctx->opcode) != 0)) \
1207 gen_set_Rc0(ctx); \
1208}
1209#define GEN_LOGICAL2(name, opc, type) \
1210__GEN_LOGICAL2(name, 0x1C, opc, type)
1211
1212#define GEN_LOGICAL1(name, opc, type) \
1213GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
1214{ \
1215 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); \
1216 gen_op_##name(); \
1217 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
1218 if (unlikely(Rc(ctx->opcode) != 0)) \
1219 gen_set_Rc0(ctx); \
1220}
1221
1222/* and & and. */
1223GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
1224/* andc & andc. */
1225GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
1226/* andi. */
1227GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1228{
1229 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1230 gen_op_andi_T0(UIMM(ctx->opcode));
1231 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1232 gen_set_Rc0(ctx);
1233}
1234/* andis. */
1235GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1236{
1237 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1238 gen_op_andi_T0(UIMM(ctx->opcode) << 16);
1239 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1240 gen_set_Rc0(ctx);
1241}
1242
1243/* cntlzw */
1244GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
1245/* eqv & eqv. */
1246GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
1247/* extsb & extsb. */
1248GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
1249/* extsh & extsh. */
1250GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
1251/* nand & nand. */
1252GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
1253/* nor & nor. */
1254GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1255
1256/* or & or. */
1257GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1258{
1259 int rs, ra, rb;
1260
1261 rs = rS(ctx->opcode);
1262 ra = rA(ctx->opcode);
1263 rb = rB(ctx->opcode);
1264 /* Optimisation for mr. ri case */
1265 if (rs != ra || rs != rb) {
1266 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1267 if (rs != rb) {
1268 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
1269 gen_op_or();
1270 }
1271 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
1272 if (unlikely(Rc(ctx->opcode) != 0))
1273 gen_set_Rc0(ctx);
1274 } else if (unlikely(Rc(ctx->opcode) != 0)) {
1275 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1276 gen_set_Rc0(ctx);
1277#if defined(TARGET_PPC64)
1278 } else {
1279 switch (rs) {
1280 case 1:
1281 /* Set process priority to low */
1282 gen_op_store_pri(2);
1283 break;
1284 case 6:
1285 /* Set process priority to medium-low */
1286 gen_op_store_pri(3);
1287 break;
1288 case 2:
1289 /* Set process priority to normal */
1290 gen_op_store_pri(4);
1291 break;
1292#if !defined(CONFIG_USER_ONLY)
1293 case 31:
1294 if (ctx->supervisor > 0) {
1295 /* Set process priority to very low */
1296 gen_op_store_pri(1);
1297 }
1298 break;
1299 case 5:
1300 if (ctx->supervisor > 0) {
1301 /* Set process priority to medium-hight */
1302 gen_op_store_pri(5);
1303 }
1304 break;
1305 case 3:
1306 if (ctx->supervisor > 0) {
1307 /* Set process priority to high */
1308 gen_op_store_pri(6);
1309 }
1310 break;
1311 case 7:
1312 if (ctx->supervisor > 1) {
1313 /* Set process priority to very high */
1314 gen_op_store_pri(7);
1315 }
1316 break;
1317#endif
1318 default:
1319 /* nop */
1320 break;
1321 }
1322#endif
1323 }
1324}
1325
1326/* orc & orc. */
1327GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
1328/* xor & xor. */
1329GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1330{
1331 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1332 /* Optimisation for "set to zero" case */
1333 if (rS(ctx->opcode) != rB(ctx->opcode)) {
1334 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1335 gen_op_xor();
1336 } else {
1337 tcg_gen_movi_tl(cpu_T[0], 0);
1338 }
1339 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1340 if (unlikely(Rc(ctx->opcode) != 0))
1341 gen_set_Rc0(ctx);
1342}
1343/* ori */
1344GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1345{
1346 target_ulong uimm = UIMM(ctx->opcode);
1347
1348 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1349 /* NOP */
1350 /* XXX: should handle special NOPs for POWER series */
1351 return;
1352 }
1353 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1354 if (likely(uimm != 0))
1355 gen_op_ori(uimm);
1356 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1357}
1358/* oris */
1359GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1360{
1361 target_ulong uimm = UIMM(ctx->opcode);
1362
1363 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1364 /* NOP */
1365 return;
1366 }
1367 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1368 if (likely(uimm != 0))
1369 gen_op_ori(uimm << 16);
1370 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1371}
1372/* xori */
1373GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1374{
1375 target_ulong uimm = UIMM(ctx->opcode);
1376
1377 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1378 /* NOP */
1379 return;
1380 }
1381 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1382 if (likely(uimm != 0))
1383 gen_op_xori(uimm);
1384 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1385}
1386
1387/* xoris */
1388GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1389{
1390 target_ulong uimm = UIMM(ctx->opcode);
1391
1392 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1393 /* NOP */
1394 return;
1395 }
1396 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1397 if (likely(uimm != 0))
1398 gen_op_xori(uimm << 16);
1399 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1400}
1401
1402/* popcntb : PowerPC 2.03 specification */
1403GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1404{
1405 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1406#if defined(TARGET_PPC64)
1407 if (ctx->sf_mode)
1408 gen_op_popcntb_64();
1409 else
1410#endif
1411 gen_op_popcntb();
1412 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1413}
1414
1415#if defined(TARGET_PPC64)
1416/* extsw & extsw. */
1417GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
1418/* cntlzd */
1419GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
1420#endif
1421
1422/*** Integer rotate ***/
1423/* rlwimi & rlwimi. */
1424GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1425{
1426 target_ulong mask;
1427 uint32_t mb, me, sh;
1428
1429 mb = MB(ctx->opcode);
1430 me = ME(ctx->opcode);
1431 sh = SH(ctx->opcode);
1432 if (likely(sh == 0)) {
1433 if (likely(mb == 0 && me == 31)) {
1434 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1435 goto do_store;
1436 } else if (likely(mb == 31 && me == 0)) {
1437 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1438 goto do_store;
1439 }
1440 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1441 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1442 goto do_mask;
1443 }
1444 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1445 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1446 gen_op_rotli32_T0(SH(ctx->opcode));
1447 do_mask:
1448#if defined(TARGET_PPC64)
1449 mb += 32;
1450 me += 32;
1451#endif
1452 mask = MASK(mb, me);
1453 gen_op_andi_T0(mask);
1454 gen_op_andi_T1(~mask);
1455 gen_op_or();
1456 do_store:
1457 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1458 if (unlikely(Rc(ctx->opcode) != 0))
1459 gen_set_Rc0(ctx);
1460}
1461/* rlwinm & rlwinm. */
1462GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1463{
1464 uint32_t mb, me, sh;
1465
1466 sh = SH(ctx->opcode);
1467 mb = MB(ctx->opcode);
1468 me = ME(ctx->opcode);
1469 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1470 if (likely(sh == 0)) {
1471 goto do_mask;
1472 }
1473 if (likely(mb == 0)) {
1474 if (likely(me == 31)) {
1475 gen_op_rotli32_T0(sh);
1476 goto do_store;
1477 } else if (likely(me == (31 - sh))) {
1478 gen_op_sli_T0(sh);
1479 goto do_store;
1480 }
1481 } else if (likely(me == 31)) {
1482 if (likely(sh == (32 - mb))) {
1483 gen_op_srli_T0(mb);
1484 goto do_store;
1485 }
1486 }
1487 gen_op_rotli32_T0(sh);
1488 do_mask:
1489#if defined(TARGET_PPC64)
1490 mb += 32;
1491 me += 32;
1492#endif
1493 gen_op_andi_T0(MASK(mb, me));
1494 do_store:
1495 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1496 if (unlikely(Rc(ctx->opcode) != 0))
1497 gen_set_Rc0(ctx);
1498}
1499/* rlwnm & rlwnm. */
1500GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1501{
1502 uint32_t mb, me;
1503
1504 mb = MB(ctx->opcode);
1505 me = ME(ctx->opcode);
1506 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1507 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1508 gen_op_rotl32_T0_T1();
1509 if (unlikely(mb != 0 || me != 31)) {
1510#if defined(TARGET_PPC64)
1511 mb += 32;
1512 me += 32;
1513#endif
1514 gen_op_andi_T0(MASK(mb, me));
1515 }
1516 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1517 if (unlikely(Rc(ctx->opcode) != 0))
1518 gen_set_Rc0(ctx);
1519}
1520
1521#if defined(TARGET_PPC64)
1522#define GEN_PPC64_R2(name, opc1, opc2) \
1523GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1524{ \
1525 gen_##name(ctx, 0); \
1526} \
1527GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1528 PPC_64B) \
1529{ \
1530 gen_##name(ctx, 1); \
1531}
1532#define GEN_PPC64_R4(name, opc1, opc2) \
1533GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1534{ \
1535 gen_##name(ctx, 0, 0); \
1536} \
1537GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
1538 PPC_64B) \
1539{ \
1540 gen_##name(ctx, 0, 1); \
1541} \
1542GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1543 PPC_64B) \
1544{ \
1545 gen_##name(ctx, 1, 0); \
1546} \
1547GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
1548 PPC_64B) \
1549{ \
1550 gen_##name(ctx, 1, 1); \
1551}
1552
1553static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
1554{
1555 if (mask >> 32)
1556 gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
1557 else
1558 gen_op_andi_T0(mask);
1559}
1560
1561static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
1562{
1563 if (mask >> 32)
1564 gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
1565 else
1566 gen_op_andi_T1(mask);
1567}
1568
1569static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1570 uint32_t me, uint32_t sh)
1571{
1572 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1573 if (likely(sh == 0)) {
1574 goto do_mask;
1575 }
1576 if (likely(mb == 0)) {
1577 if (likely(me == 63)) {
1578 gen_op_rotli64_T0(sh);
1579 goto do_store;
1580 } else if (likely(me == (63 - sh))) {
1581 gen_op_sli_T0(sh);
1582 goto do_store;
1583 }
1584 } else if (likely(me == 63)) {
1585 if (likely(sh == (64 - mb))) {
1586 gen_op_srli_T0_64(mb);
1587 goto do_store;
1588 }
1589 }
1590 gen_op_rotli64_T0(sh);
1591 do_mask:
1592 gen_andi_T0_64(ctx, MASK(mb, me));
1593 do_store:
1594 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1595 if (unlikely(Rc(ctx->opcode) != 0))
1596 gen_set_Rc0(ctx);
1597}
1598/* rldicl - rldicl. */
1599static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1600{
1601 uint32_t sh, mb;
1602
1603 sh = SH(ctx->opcode) | (shn << 5);
1604 mb = MB(ctx->opcode) | (mbn << 5);
1605 gen_rldinm(ctx, mb, 63, sh);
1606}
1607GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1608/* rldicr - rldicr. */
1609static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1610{
1611 uint32_t sh, me;
1612
1613 sh = SH(ctx->opcode) | (shn << 5);
1614 me = MB(ctx->opcode) | (men << 5);
1615 gen_rldinm(ctx, 0, me, sh);
1616}
1617GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1618/* rldic - rldic. */
1619static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1620{
1621 uint32_t sh, mb;
1622
1623 sh = SH(ctx->opcode) | (shn << 5);
1624 mb = MB(ctx->opcode) | (mbn << 5);
1625 gen_rldinm(ctx, mb, 63 - sh, sh);
1626}
1627GEN_PPC64_R4(rldic, 0x1E, 0x04);
1628
1629static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1630 uint32_t me)
1631{
1632 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1633 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1634 gen_op_rotl64_T0_T1();
1635 if (unlikely(mb != 0 || me != 63)) {
1636 gen_andi_T0_64(ctx, MASK(mb, me));
1637 }
1638 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1639 if (unlikely(Rc(ctx->opcode) != 0))
1640 gen_set_Rc0(ctx);
1641}
1642
1643/* rldcl - rldcl. */
1644static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1645{
1646 uint32_t mb;
1647
1648 mb = MB(ctx->opcode) | (mbn << 5);
1649 gen_rldnm(ctx, mb, 63);
1650}
1651GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1652/* rldcr - rldcr. */
1653static always_inline void gen_rldcr (DisasContext *ctx, int men)
1654{
1655 uint32_t me;
1656
1657 me = MB(ctx->opcode) | (men << 5);
1658 gen_rldnm(ctx, 0, me);
1659}
1660GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1661/* rldimi - rldimi. */
1662static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1663{
1664 uint64_t mask;
1665 uint32_t sh, mb, me;
1666
1667 sh = SH(ctx->opcode) | (shn << 5);
1668 mb = MB(ctx->opcode) | (mbn << 5);
1669 me = 63 - sh;
1670 if (likely(sh == 0)) {
1671 if (likely(mb == 0)) {
1672 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1673 goto do_store;
1674 }
1675 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1676 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1677 goto do_mask;
1678 }
1679 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1680 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1681 gen_op_rotli64_T0(sh);
1682 do_mask:
1683 mask = MASK(mb, me);
1684 gen_andi_T0_64(ctx, mask);
1685 gen_andi_T1_64(ctx, ~mask);
1686 gen_op_or();
1687 do_store:
1688 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1689 if (unlikely(Rc(ctx->opcode) != 0))
1690 gen_set_Rc0(ctx);
1691}
1692GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1693#endif
1694
1695/*** Integer shift ***/
1696/* slw & slw. */
1697__GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
1698/* sraw & sraw. */
1699__GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
1700/* srawi & srawi. */
1701GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1702{
1703 int mb, me;
1704 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1705 if (SH(ctx->opcode) != 0) {
1706 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1707 mb = 32 - SH(ctx->opcode);
1708 me = 31;
1709#if defined(TARGET_PPC64)
1710 mb += 32;
1711 me += 32;
1712#endif
1713 gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
1714 }
1715 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1716 if (unlikely(Rc(ctx->opcode) != 0))
1717 gen_set_Rc0(ctx);
1718}
1719/* srw & srw. */
1720__GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
1721
1722#if defined(TARGET_PPC64)
1723/* sld & sld. */
1724__GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
1725/* srad & srad. */
1726__GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
1727/* sradi & sradi. */
1728static always_inline void gen_sradi (DisasContext *ctx, int n)
1729{
1730 uint64_t mask;
1731 int sh, mb, me;
1732
1733 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1734 sh = SH(ctx->opcode) + (n << 5);
1735 if (sh != 0) {
1736 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1737 mb = 64 - SH(ctx->opcode);
1738 me = 63;
1739 mask = MASK(mb, me);
1740 gen_op_sradi(sh, mask >> 32, mask);
1741 }
1742 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1743 if (unlikely(Rc(ctx->opcode) != 0))
1744 gen_set_Rc0(ctx);
1745}
1746GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1747{
1748 gen_sradi(ctx, 0);
1749}
1750GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1751{
1752 gen_sradi(ctx, 1);
1753}
1754/* srd & srd. */
1755__GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
1756#endif
1757
1758/*** Floating-Point arithmetic ***/
1759#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1760GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1761{ \
1762 if (unlikely(!ctx->fpu_enabled)) { \
1763 GEN_EXCP_NO_FP(ctx); \
1764 return; \
1765 } \
1766 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]); \
1767 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]); \
1768 tcg_gen_mov_i64(cpu_FT[2], cpu_fpr[rB(ctx->opcode)]); \
1769 gen_reset_fpstatus(); \
1770 gen_op_f##op(); \
1771 if (isfloat) { \
1772 gen_op_frsp(); \
1773 } \
1774 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
1775 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1776}
1777
1778#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
1779_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
1780_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1781
1782#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1783GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1784{ \
1785 if (unlikely(!ctx->fpu_enabled)) { \
1786 GEN_EXCP_NO_FP(ctx); \
1787 return; \
1788 } \
1789 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]); \
1790 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]); \
1791 gen_reset_fpstatus(); \
1792 gen_op_f##op(); \
1793 if (isfloat) { \
1794 gen_op_frsp(); \
1795 } \
1796 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
1797 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1798}
1799#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
1800_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1801_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1802
1803#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1804GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1805{ \
1806 if (unlikely(!ctx->fpu_enabled)) { \
1807 GEN_EXCP_NO_FP(ctx); \
1808 return; \
1809 } \
1810 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]); \
1811 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rC(ctx->opcode)]); \
1812 gen_reset_fpstatus(); \
1813 gen_op_f##op(); \
1814 if (isfloat) { \
1815 gen_op_frsp(); \
1816 } \
1817 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
1818 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1819}
1820#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
1821_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1822_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1823
1824#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1825GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1826{ \
1827 if (unlikely(!ctx->fpu_enabled)) { \
1828 GEN_EXCP_NO_FP(ctx); \
1829 return; \
1830 } \
1831 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]); \
1832 gen_reset_fpstatus(); \
1833 gen_op_f##name(); \
1834 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
1835 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1836}
1837
1838#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1839GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1840{ \
1841 if (unlikely(!ctx->fpu_enabled)) { \
1842 GEN_EXCP_NO_FP(ctx); \
1843 return; \
1844 } \
1845 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]); \
1846 gen_reset_fpstatus(); \
1847 gen_op_f##name(); \
1848 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
1849 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1850}
1851
1852/* fadd - fadds */
1853GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1854/* fdiv - fdivs */
1855GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1856/* fmul - fmuls */
1857GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
1858
1859/* fre */
1860GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1861
1862/* fres */
1863GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1864
1865/* frsqrte */
1866GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
1867
1868/* frsqrtes */
1869static always_inline void gen_op_frsqrtes (void)
1870{
1871 gen_op_frsqrte();
1872 gen_op_frsp();
1873}
1874GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
1875
1876/* fsel */
1877_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1878/* fsub - fsubs */
1879GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1880/* Optional: */
1881/* fsqrt */
1882GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1883{
1884 if (unlikely(!ctx->fpu_enabled)) {
1885 GEN_EXCP_NO_FP(ctx);
1886 return;
1887 }
1888 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
1889 gen_reset_fpstatus();
1890 gen_op_fsqrt();
1891 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
1892 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1893}
1894
1895GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1896{
1897 if (unlikely(!ctx->fpu_enabled)) {
1898 GEN_EXCP_NO_FP(ctx);
1899 return;
1900 }
1901 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
1902 gen_reset_fpstatus();
1903 gen_op_fsqrt();
1904 gen_op_frsp();
1905 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
1906 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1907}
1908
1909/*** Floating-Point multiply-and-add ***/
1910/* fmadd - fmadds */
1911GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1912/* fmsub - fmsubs */
1913GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1914/* fnmadd - fnmadds */
1915GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1916/* fnmsub - fnmsubs */
1917GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1918
1919/*** Floating-Point round & convert ***/
1920/* fctiw */
1921GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1922/* fctiwz */
1923GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1924/* frsp */
1925GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
1926#if defined(TARGET_PPC64)
1927/* fcfid */
1928GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
1929/* fctid */
1930GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
1931/* fctidz */
1932GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
1933#endif
1934
1935/* frin */
1936GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1937/* friz */
1938GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1939/* frip */
1940GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1941/* frim */
1942GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1943
1944/*** Floating-Point compare ***/
1945/* fcmpo */
1946GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1947{
1948 if (unlikely(!ctx->fpu_enabled)) {
1949 GEN_EXCP_NO_FP(ctx);
1950 return;
1951 }
1952 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
1953 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
1954 gen_reset_fpstatus();
1955 gen_op_fcmpo();
1956 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1957 gen_op_float_check_status();
1958}
1959
1960/* fcmpu */
1961GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1962{
1963 if (unlikely(!ctx->fpu_enabled)) {
1964 GEN_EXCP_NO_FP(ctx);
1965 return;
1966 }
1967 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rA(ctx->opcode)]);
1968 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rB(ctx->opcode)]);
1969 gen_reset_fpstatus();
1970 gen_op_fcmpu();
1971 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
1972 gen_op_float_check_status();
1973}
1974
1975/*** Floating-point move ***/
1976/* fabs */
1977/* XXX: beware that fabs never checks for NaNs nor update FPSCR */
1978GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1979
1980/* fmr - fmr. */
1981/* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1982GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1983{
1984 if (unlikely(!ctx->fpu_enabled)) {
1985 GEN_EXCP_NO_FP(ctx);
1986 return;
1987 }
1988 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
1989 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
1990 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1991}
1992
1993/* fnabs */
1994/* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
1995GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1996/* fneg */
1997/* XXX: beware that fneg never checks for NaNs nor update FPSCR */
1998GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1999
2000/*** Floating-Point status & ctrl register ***/
2001/* mcrfs */
2002GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
2003{
2004 int bfa;
2005
2006 if (unlikely(!ctx->fpu_enabled)) {
2007 GEN_EXCP_NO_FP(ctx);
2008 return;
2009 }
2010 gen_optimize_fprf();
2011 bfa = 4 * (7 - crfS(ctx->opcode));
2012 gen_op_load_fpscr_T0(bfa);
2013 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
2014 gen_op_fpscr_resetbit(~(0xF << bfa));
2015}
2016
2017/* mffs */
2018GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
2019{
2020 if (unlikely(!ctx->fpu_enabled)) {
2021 GEN_EXCP_NO_FP(ctx);
2022 return;
2023 }
2024 gen_optimize_fprf();
2025 gen_reset_fpstatus();
2026 gen_op_load_fpscr_FT0();
2027 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
2028 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
2029}
2030
2031/* mtfsb0 */
2032GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
2033{
2034 uint8_t crb;
2035
2036 if (unlikely(!ctx->fpu_enabled)) {
2037 GEN_EXCP_NO_FP(ctx);
2038 return;
2039 }
2040 crb = 32 - (crbD(ctx->opcode) >> 2);
2041 gen_optimize_fprf();
2042 gen_reset_fpstatus();
2043 if (likely(crb != 30 && crb != 29))
2044 gen_op_fpscr_resetbit(~(1 << crb));
2045 if (unlikely(Rc(ctx->opcode) != 0)) {
2046 gen_op_load_fpcc();
2047 gen_op_set_Rc0();
2048 }
2049}
2050
2051/* mtfsb1 */
2052GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2053{
2054 uint8_t crb;
2055
2056 if (unlikely(!ctx->fpu_enabled)) {
2057 GEN_EXCP_NO_FP(ctx);
2058 return;
2059 }
2060 crb = 32 - (crbD(ctx->opcode) >> 2);
2061 gen_optimize_fprf();
2062 gen_reset_fpstatus();
2063 /* XXX: we pretend we can only do IEEE floating-point computations */
2064 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
2065 gen_op_fpscr_setbit(crb);
2066 if (unlikely(Rc(ctx->opcode) != 0)) {
2067 gen_op_load_fpcc();
2068 gen_op_set_Rc0();
2069 }
2070 /* We can raise a differed exception */
2071 gen_op_float_check_status();
2072}
2073
2074/* mtfsf */
2075GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2076{
2077 if (unlikely(!ctx->fpu_enabled)) {
2078 GEN_EXCP_NO_FP(ctx);
2079 return;
2080 }
2081 gen_optimize_fprf();
2082 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rB(ctx->opcode)]);
2083 gen_reset_fpstatus();
2084 gen_op_store_fpscr(FM(ctx->opcode));
2085 if (unlikely(Rc(ctx->opcode) != 0)) {
2086 gen_op_load_fpcc();
2087 gen_op_set_Rc0();
2088 }
2089 /* We can raise a differed exception */
2090 gen_op_float_check_status();
2091}
2092
2093/* mtfsfi */
2094GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2095{
2096 int bf, sh;
2097
2098 if (unlikely(!ctx->fpu_enabled)) {
2099 GEN_EXCP_NO_FP(ctx);
2100 return;
2101 }
2102 bf = crbD(ctx->opcode) >> 2;
2103 sh = 7 - bf;
2104 gen_optimize_fprf();
2105 tcg_gen_movi_i64(cpu_FT[0], FPIMM(ctx->opcode) << (4 * sh));
2106 gen_reset_fpstatus();
2107 gen_op_store_fpscr(1 << sh);
2108 if (unlikely(Rc(ctx->opcode) != 0)) {
2109 gen_op_load_fpcc();
2110 gen_op_set_Rc0();
2111 }
2112 /* We can raise a differed exception */
2113 gen_op_float_check_status();
2114}
2115
2116/*** Addressing modes ***/
2117/* Register indirect with immediate index : EA = (rA|0) + SIMM */
2118static always_inline void gen_addr_imm_index (DisasContext *ctx,
2119 target_long maskl)
2120{
2121 target_long simm = SIMM(ctx->opcode);
2122
2123 simm &= ~maskl;
2124 if (rA(ctx->opcode) == 0) {
2125 tcg_gen_movi_tl(cpu_T[0], simm);
2126 } else {
2127 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2128 if (likely(simm != 0))
2129 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm);
2130 }
2131#ifdef DEBUG_MEMORY_ACCESSES
2132 gen_op_print_mem_EA();
2133#endif
2134}
2135
2136static always_inline void gen_addr_reg_index (DisasContext *ctx)
2137{
2138 if (rA(ctx->opcode) == 0) {
2139 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
2140 } else {
2141 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2142 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
2143 tcg_gen_add_tl(cpu_T[0], cpu_T[0], cpu_T[1]);
2144 }
2145#ifdef DEBUG_MEMORY_ACCESSES
2146 gen_op_print_mem_EA();
2147#endif
2148}
2149
2150static always_inline void gen_addr_register (DisasContext *ctx)
2151{
2152 if (rA(ctx->opcode) == 0) {
2153 tcg_gen_movi_tl(cpu_T[0], 0);
2154 } else {
2155 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2156 }
2157#ifdef DEBUG_MEMORY_ACCESSES
2158 gen_op_print_mem_EA();
2159#endif
2160}
2161
2162#if defined(TARGET_PPC64)
2163#define _GEN_MEM_FUNCS(name, mode) \
2164 &gen_op_##name##_##mode, \
2165 &gen_op_##name##_le_##mode, \
2166 &gen_op_##name##_64_##mode, \
2167 &gen_op_##name##_le_64_##mode
2168#else
2169#define _GEN_MEM_FUNCS(name, mode) \
2170 &gen_op_##name##_##mode, \
2171 &gen_op_##name##_le_##mode
2172#endif
2173#if defined(CONFIG_USER_ONLY)
2174#if defined(TARGET_PPC64)
2175#define NB_MEM_FUNCS 4
2176#else
2177#define NB_MEM_FUNCS 2
2178#endif
2179#define GEN_MEM_FUNCS(name) \
2180 _GEN_MEM_FUNCS(name, raw)
2181#else
2182#if defined(TARGET_PPC64)
2183#define NB_MEM_FUNCS 12
2184#else
2185#define NB_MEM_FUNCS 6
2186#endif
2187#define GEN_MEM_FUNCS(name) \
2188 _GEN_MEM_FUNCS(name, user), \
2189 _GEN_MEM_FUNCS(name, kernel), \
2190 _GEN_MEM_FUNCS(name, hypv)
2191#endif
2192
2193/*** Integer load ***/
2194#define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
2195/* Byte access routine are endian safe */
2196#define gen_op_lbz_le_raw gen_op_lbz_raw
2197#define gen_op_lbz_le_user gen_op_lbz_user
2198#define gen_op_lbz_le_kernel gen_op_lbz_kernel
2199#define gen_op_lbz_le_hypv gen_op_lbz_hypv
2200#define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
2201#define gen_op_lbz_le_64_user gen_op_lbz_64_user
2202#define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
2203#define gen_op_lbz_le_64_hypv gen_op_lbz_64_hypv
2204#define gen_op_stb_le_raw gen_op_stb_raw
2205#define gen_op_stb_le_user gen_op_stb_user
2206#define gen_op_stb_le_kernel gen_op_stb_kernel
2207#define gen_op_stb_le_hypv gen_op_stb_hypv
2208#define gen_op_stb_le_64_raw gen_op_stb_64_raw
2209#define gen_op_stb_le_64_user gen_op_stb_64_user
2210#define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
2211#define gen_op_stb_le_64_hypv gen_op_stb_64_hypv
2212#define OP_LD_TABLE(width) \
2213static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = { \
2214 GEN_MEM_FUNCS(l##width), \
2215};
2216#define OP_ST_TABLE(width) \
2217static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = { \
2218 GEN_MEM_FUNCS(st##width), \
2219};
2220
2221#define GEN_LD(width, opc, type) \
2222GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2223{ \
2224 gen_addr_imm_index(ctx, 0); \
2225 op_ldst(l##width); \
2226 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2227}
2228
2229#define GEN_LDU(width, opc, type) \
2230GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2231{ \
2232 if (unlikely(rA(ctx->opcode) == 0 || \
2233 rA(ctx->opcode) == rD(ctx->opcode))) { \
2234 GEN_EXCP_INVAL(ctx); \
2235 return; \
2236 } \
2237 if (type == PPC_64B) \
2238 gen_addr_imm_index(ctx, 0x03); \
2239 else \
2240 gen_addr_imm_index(ctx, 0); \
2241 op_ldst(l##width); \
2242 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2243 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2244}
2245
2246#define GEN_LDUX(width, opc2, opc3, type) \
2247GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2248{ \
2249 if (unlikely(rA(ctx->opcode) == 0 || \
2250 rA(ctx->opcode) == rD(ctx->opcode))) { \
2251 GEN_EXCP_INVAL(ctx); \
2252 return; \
2253 } \
2254 gen_addr_reg_index(ctx); \
2255 op_ldst(l##width); \
2256 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2257 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2258}
2259
2260#define GEN_LDX(width, opc2, opc3, type) \
2261GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2262{ \
2263 gen_addr_reg_index(ctx); \
2264 op_ldst(l##width); \
2265 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2266}
2267
2268#define GEN_LDS(width, op, type) \
2269OP_LD_TABLE(width); \
2270GEN_LD(width, op | 0x20, type); \
2271GEN_LDU(width, op | 0x21, type); \
2272GEN_LDUX(width, 0x17, op | 0x01, type); \
2273GEN_LDX(width, 0x17, op | 0x00, type)
2274
2275/* lbz lbzu lbzux lbzx */
2276GEN_LDS(bz, 0x02, PPC_INTEGER);
2277/* lha lhau lhaux lhax */
2278GEN_LDS(ha, 0x0A, PPC_INTEGER);
2279/* lhz lhzu lhzux lhzx */
2280GEN_LDS(hz, 0x08, PPC_INTEGER);
2281/* lwz lwzu lwzux lwzx */
2282GEN_LDS(wz, 0x00, PPC_INTEGER);
2283#if defined(TARGET_PPC64)
2284OP_LD_TABLE(wa);
2285OP_LD_TABLE(d);
2286/* lwaux */
2287GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
2288/* lwax */
2289GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
2290/* ldux */
2291GEN_LDUX(d, 0x15, 0x01, PPC_64B);
2292/* ldx */
2293GEN_LDX(d, 0x15, 0x00, PPC_64B);
2294GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2295{
2296 if (Rc(ctx->opcode)) {
2297 if (unlikely(rA(ctx->opcode) == 0 ||
2298 rA(ctx->opcode) == rD(ctx->opcode))) {
2299 GEN_EXCP_INVAL(ctx);
2300 return;
2301 }
2302 }
2303 gen_addr_imm_index(ctx, 0x03);
2304 if (ctx->opcode & 0x02) {
2305 /* lwa (lwau is undefined) */
2306 op_ldst(lwa);
2307 } else {
2308 /* ld - ldu */
2309 op_ldst(ld);
2310 }
2311 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2312 if (Rc(ctx->opcode))
2313 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2314}
2315/* lq */
2316GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2317{
2318#if defined(CONFIG_USER_ONLY)
2319 GEN_EXCP_PRIVOPC(ctx);
2320#else
2321 int ra, rd;
2322
2323 /* Restore CPU state */
2324 if (unlikely(ctx->supervisor == 0)) {
2325 GEN_EXCP_PRIVOPC(ctx);
2326 return;
2327 }
2328 ra = rA(ctx->opcode);
2329 rd = rD(ctx->opcode);
2330 if (unlikely((rd & 1) || rd == ra)) {
2331 GEN_EXCP_INVAL(ctx);
2332 return;
2333 }
2334 if (unlikely(ctx->mem_idx & 1)) {
2335 /* Little-endian mode is not handled */
2336 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2337 return;
2338 }
2339 gen_addr_imm_index(ctx, 0x0F);
2340 op_ldst(ld);
2341 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[1]);
2342 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 8);
2343 op_ldst(ld);
2344 tcg_gen_mov_tl(cpu_gpr[rd + 1], cpu_T[1]);
2345#endif
2346}
2347#endif
2348
2349/*** Integer store ***/
2350#define GEN_ST(width, opc, type) \
2351GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2352{ \
2353 gen_addr_imm_index(ctx, 0); \
2354 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2355 op_ldst(st##width); \
2356}
2357
2358#define GEN_STU(width, opc, type) \
2359GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2360{ \
2361 if (unlikely(rA(ctx->opcode) == 0)) { \
2362 GEN_EXCP_INVAL(ctx); \
2363 return; \
2364 } \
2365 if (type == PPC_64B) \
2366 gen_addr_imm_index(ctx, 0x03); \
2367 else \
2368 gen_addr_imm_index(ctx, 0); \
2369 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2370 op_ldst(st##width); \
2371 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2372}
2373
2374#define GEN_STUX(width, opc2, opc3, type) \
2375GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2376{ \
2377 if (unlikely(rA(ctx->opcode) == 0)) { \
2378 GEN_EXCP_INVAL(ctx); \
2379 return; \
2380 } \
2381 gen_addr_reg_index(ctx); \
2382 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2383 op_ldst(st##width); \
2384 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2385}
2386
2387#define GEN_STX(width, opc2, opc3, type) \
2388GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2389{ \
2390 gen_addr_reg_index(ctx); \
2391 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2392 op_ldst(st##width); \
2393}
2394
2395#define GEN_STS(width, op, type) \
2396OP_ST_TABLE(width); \
2397GEN_ST(width, op | 0x20, type); \
2398GEN_STU(width, op | 0x21, type); \
2399GEN_STUX(width, 0x17, op | 0x01, type); \
2400GEN_STX(width, 0x17, op | 0x00, type)
2401
2402/* stb stbu stbux stbx */
2403GEN_STS(b, 0x06, PPC_INTEGER);
2404/* sth sthu sthux sthx */
2405GEN_STS(h, 0x0C, PPC_INTEGER);
2406/* stw stwu stwux stwx */
2407GEN_STS(w, 0x04, PPC_INTEGER);
2408#if defined(TARGET_PPC64)
2409OP_ST_TABLE(d);
2410GEN_STUX(d, 0x15, 0x05, PPC_64B);
2411GEN_STX(d, 0x15, 0x04, PPC_64B);
2412GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2413{
2414 int rs;
2415
2416 rs = rS(ctx->opcode);
2417 if ((ctx->opcode & 0x3) == 0x2) {
2418#if defined(CONFIG_USER_ONLY)
2419 GEN_EXCP_PRIVOPC(ctx);
2420#else
2421 /* stq */
2422 if (unlikely(ctx->supervisor == 0)) {
2423 GEN_EXCP_PRIVOPC(ctx);
2424 return;
2425 }
2426 if (unlikely(rs & 1)) {
2427 GEN_EXCP_INVAL(ctx);
2428 return;
2429 }
2430 if (unlikely(ctx->mem_idx & 1)) {
2431 /* Little-endian mode is not handled */
2432 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2433 return;
2434 }
2435 gen_addr_imm_index(ctx, 0x03);
2436 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2437 op_ldst(std);
2438 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], 8);
2439 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs + 1]);
2440 op_ldst(std);
2441#endif
2442 } else {
2443 /* std / stdu */
2444 if (Rc(ctx->opcode)) {
2445 if (unlikely(rA(ctx->opcode) == 0)) {
2446 GEN_EXCP_INVAL(ctx);
2447 return;
2448 }
2449 }
2450 gen_addr_imm_index(ctx, 0x03);
2451 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2452 op_ldst(std);
2453 if (Rc(ctx->opcode))
2454 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2455 }
2456}
2457#endif
2458/*** Integer load and store with byte reverse ***/
2459/* lhbrx */
2460OP_LD_TABLE(hbr);
2461GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
2462/* lwbrx */
2463OP_LD_TABLE(wbr);
2464GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
2465/* sthbrx */
2466OP_ST_TABLE(hbr);
2467GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
2468/* stwbrx */
2469OP_ST_TABLE(wbr);
2470GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
2471
2472/*** Integer load and store multiple ***/
2473#define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2474static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
2475 GEN_MEM_FUNCS(lmw),
2476};
2477static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
2478 GEN_MEM_FUNCS(stmw),
2479};
2480
2481/* lmw */
2482GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2483{
2484 /* NIP cannot be restored if the memory exception comes from an helper */
2485 gen_update_nip(ctx, ctx->nip - 4);
2486 gen_addr_imm_index(ctx, 0);
2487 op_ldstm(lmw, rD(ctx->opcode));
2488}
2489
2490/* stmw */
2491GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2492{
2493 /* NIP cannot be restored if the memory exception comes from an helper */
2494 gen_update_nip(ctx, ctx->nip - 4);
2495 gen_addr_imm_index(ctx, 0);
2496 op_ldstm(stmw, rS(ctx->opcode));
2497}
2498
2499/*** Integer load and store strings ***/
2500#define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2501#define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2502/* string load & stores are by definition endian-safe */
2503#define gen_op_lswi_le_raw gen_op_lswi_raw
2504#define gen_op_lswi_le_user gen_op_lswi_user
2505#define gen_op_lswi_le_kernel gen_op_lswi_kernel
2506#define gen_op_lswi_le_hypv gen_op_lswi_hypv
2507#define gen_op_lswi_le_64_raw gen_op_lswi_raw
2508#define gen_op_lswi_le_64_user gen_op_lswi_user
2509#define gen_op_lswi_le_64_kernel gen_op_lswi_kernel
2510#define gen_op_lswi_le_64_hypv gen_op_lswi_hypv
2511static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
2512 GEN_MEM_FUNCS(lswi),
2513};
2514#define gen_op_lswx_le_raw gen_op_lswx_raw
2515#define gen_op_lswx_le_user gen_op_lswx_user
2516#define gen_op_lswx_le_kernel gen_op_lswx_kernel
2517#define gen_op_lswx_le_hypv gen_op_lswx_hypv
2518#define gen_op_lswx_le_64_raw gen_op_lswx_raw
2519#define gen_op_lswx_le_64_user gen_op_lswx_user
2520#define gen_op_lswx_le_64_kernel gen_op_lswx_kernel
2521#define gen_op_lswx_le_64_hypv gen_op_lswx_hypv
2522static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
2523 GEN_MEM_FUNCS(lswx),
2524};
2525#define gen_op_stsw_le_raw gen_op_stsw_raw
2526#define gen_op_stsw_le_user gen_op_stsw_user
2527#define gen_op_stsw_le_kernel gen_op_stsw_kernel
2528#define gen_op_stsw_le_hypv gen_op_stsw_hypv
2529#define gen_op_stsw_le_64_raw gen_op_stsw_raw
2530#define gen_op_stsw_le_64_user gen_op_stsw_user
2531#define gen_op_stsw_le_64_kernel gen_op_stsw_kernel
2532#define gen_op_stsw_le_64_hypv gen_op_stsw_hypv
2533static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
2534 GEN_MEM_FUNCS(stsw),
2535};
2536
2537/* lswi */
2538/* PowerPC32 specification says we must generate an exception if
2539 * rA is in the range of registers to be loaded.
2540 * In an other hand, IBM says this is valid, but rA won't be loaded.
2541 * For now, I'll follow the spec...
2542 */
2543GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
2544{
2545 int nb = NB(ctx->opcode);
2546 int start = rD(ctx->opcode);
2547 int ra = rA(ctx->opcode);
2548 int nr;
2549
2550 if (nb == 0)
2551 nb = 32;
2552 nr = nb / 4;
2553 if (unlikely(((start + nr) > 32 &&
2554 start <= ra && (start + nr - 32) > ra) ||
2555 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2556 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
2557 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
2558 return;
2559 }
2560 /* NIP cannot be restored if the memory exception comes from an helper */
2561 gen_update_nip(ctx, ctx->nip - 4);
2562 gen_addr_register(ctx);
2563 tcg_gen_movi_tl(cpu_T[1], nb);
2564 op_ldsts(lswi, start);
2565}
2566
2567/* lswx */
2568GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
2569{
2570 int ra = rA(ctx->opcode);
2571 int rb = rB(ctx->opcode);
2572
2573 /* NIP cannot be restored if the memory exception comes from an helper */
2574 gen_update_nip(ctx, ctx->nip - 4);
2575 gen_addr_reg_index(ctx);
2576 if (ra == 0) {
2577 ra = rb;
2578 }
2579 gen_op_load_xer_bc();
2580 op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
2581}
2582
2583/* stswi */
2584GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
2585{
2586 int nb = NB(ctx->opcode);
2587
2588 /* NIP cannot be restored if the memory exception comes from an helper */
2589 gen_update_nip(ctx, ctx->nip - 4);
2590 gen_addr_register(ctx);
2591 if (nb == 0)
2592 nb = 32;
2593 tcg_gen_movi_tl(cpu_T[1], nb);
2594 op_ldsts(stsw, rS(ctx->opcode));
2595}
2596
2597/* stswx */
2598GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
2599{
2600 /* NIP cannot be restored if the memory exception comes from an helper */
2601 gen_update_nip(ctx, ctx->nip - 4);
2602 gen_addr_reg_index(ctx);
2603 gen_op_load_xer_bc();
2604 op_ldsts(stsw, rS(ctx->opcode));
2605}
2606
2607/*** Memory synchronisation ***/
2608/* eieio */
2609GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
2610{
2611}
2612
2613/* isync */
2614GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
2615{
2616 GEN_STOP(ctx);
2617}
2618
2619#define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2620#define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2621static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
2622 GEN_MEM_FUNCS(lwarx),
2623};
2624static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
2625 GEN_MEM_FUNCS(stwcx),
2626};
2627
2628/* lwarx */
2629GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
2630{
2631 /* NIP cannot be restored if the memory exception comes from an helper */
2632 gen_update_nip(ctx, ctx->nip - 4);
2633 gen_addr_reg_index(ctx);
2634 op_lwarx();
2635 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2636}
2637
2638/* stwcx. */
2639GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
2640{
2641 /* NIP cannot be restored if the memory exception comes from an helper */
2642 gen_update_nip(ctx, ctx->nip - 4);
2643 gen_addr_reg_index(ctx);
2644 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
2645 op_stwcx();
2646}
2647
2648#if defined(TARGET_PPC64)
2649#define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
2650#define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2651static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
2652 GEN_MEM_FUNCS(ldarx),
2653};
2654static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
2655 GEN_MEM_FUNCS(stdcx),
2656};
2657
2658/* ldarx */
2659GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
2660{
2661 /* NIP cannot be restored if the memory exception comes from an helper */
2662 gen_update_nip(ctx, ctx->nip - 4);
2663 gen_addr_reg_index(ctx);
2664 op_ldarx();
2665 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2666}
2667
2668/* stdcx. */
2669GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
2670{
2671 /* NIP cannot be restored if the memory exception comes from an helper */
2672 gen_update_nip(ctx, ctx->nip - 4);
2673 gen_addr_reg_index(ctx);
2674 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
2675 op_stdcx();
2676}
2677#endif /* defined(TARGET_PPC64) */
2678
2679/* sync */
2680GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
2681{
2682}
2683
2684/* wait */
2685GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
2686{
2687 /* Stop translation, as the CPU is supposed to sleep from now */
2688 gen_op_wait();
2689 GEN_EXCP(ctx, EXCP_HLT, 1);
2690}
2691
2692/*** Floating-point load ***/
2693#define GEN_LDF(width, opc, type) \
2694GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2695{ \
2696 if (unlikely(!ctx->fpu_enabled)) { \
2697 GEN_EXCP_NO_FP(ctx); \
2698 return; \
2699 } \
2700 gen_addr_imm_index(ctx, 0); \
2701 op_ldst(l##width); \
2702 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
2703}
2704
2705#define GEN_LDUF(width, opc, type) \
2706GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2707{ \
2708 if (unlikely(!ctx->fpu_enabled)) { \
2709 GEN_EXCP_NO_FP(ctx); \
2710 return; \
2711 } \
2712 if (unlikely(rA(ctx->opcode) == 0)) { \
2713 GEN_EXCP_INVAL(ctx); \
2714 return; \
2715 } \
2716 gen_addr_imm_index(ctx, 0); \
2717 op_ldst(l##width); \
2718 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
2719 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2720}
2721
2722#define GEN_LDUXF(width, opc, type) \
2723GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
2724{ \
2725 if (unlikely(!ctx->fpu_enabled)) { \
2726 GEN_EXCP_NO_FP(ctx); \
2727 return; \
2728 } \
2729 if (unlikely(rA(ctx->opcode) == 0)) { \
2730 GEN_EXCP_INVAL(ctx); \
2731 return; \
2732 } \
2733 gen_addr_reg_index(ctx); \
2734 op_ldst(l##width); \
2735 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
2736 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2737}
2738
2739#define GEN_LDXF(width, opc2, opc3, type) \
2740GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2741{ \
2742 if (unlikely(!ctx->fpu_enabled)) { \
2743 GEN_EXCP_NO_FP(ctx); \
2744 return; \
2745 } \
2746 gen_addr_reg_index(ctx); \
2747 op_ldst(l##width); \
2748 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]); \
2749}
2750
2751#define GEN_LDFS(width, op, type) \
2752OP_LD_TABLE(width); \
2753GEN_LDF(width, op | 0x20, type); \
2754GEN_LDUF(width, op | 0x21, type); \
2755GEN_LDUXF(width, op | 0x01, type); \
2756GEN_LDXF(width, 0x17, op | 0x00, type)
2757
2758/* lfd lfdu lfdux lfdx */
2759GEN_LDFS(fd, 0x12, PPC_FLOAT);
2760/* lfs lfsu lfsux lfsx */
2761GEN_LDFS(fs, 0x10, PPC_FLOAT);
2762
2763/*** Floating-point store ***/
2764#define GEN_STF(width, opc, type) \
2765GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2766{ \
2767 if (unlikely(!ctx->fpu_enabled)) { \
2768 GEN_EXCP_NO_FP(ctx); \
2769 return; \
2770 } \
2771 gen_addr_imm_index(ctx, 0); \
2772 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
2773 op_ldst(st##width); \
2774}
2775
2776#define GEN_STUF(width, opc, type) \
2777GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2778{ \
2779 if (unlikely(!ctx->fpu_enabled)) { \
2780 GEN_EXCP_NO_FP(ctx); \
2781 return; \
2782 } \
2783 if (unlikely(rA(ctx->opcode) == 0)) { \
2784 GEN_EXCP_INVAL(ctx); \
2785 return; \
2786 } \
2787 gen_addr_imm_index(ctx, 0); \
2788 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
2789 op_ldst(st##width); \
2790 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2791}
2792
2793#define GEN_STUXF(width, opc, type) \
2794GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
2795{ \
2796 if (unlikely(!ctx->fpu_enabled)) { \
2797 GEN_EXCP_NO_FP(ctx); \
2798 return; \
2799 } \
2800 if (unlikely(rA(ctx->opcode) == 0)) { \
2801 GEN_EXCP_INVAL(ctx); \
2802 return; \
2803 } \
2804 gen_addr_reg_index(ctx); \
2805 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
2806 op_ldst(st##width); \
2807 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2808}
2809
2810#define GEN_STXF(width, opc2, opc3, type) \
2811GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2812{ \
2813 if (unlikely(!ctx->fpu_enabled)) { \
2814 GEN_EXCP_NO_FP(ctx); \
2815 return; \
2816 } \
2817 gen_addr_reg_index(ctx); \
2818 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]); \
2819 op_ldst(st##width); \
2820}
2821
2822#define GEN_STFS(width, op, type) \
2823OP_ST_TABLE(width); \
2824GEN_STF(width, op | 0x20, type); \
2825GEN_STUF(width, op | 0x21, type); \
2826GEN_STUXF(width, op | 0x01, type); \
2827GEN_STXF(width, 0x17, op | 0x00, type)
2828
2829/* stfd stfdu stfdux stfdx */
2830GEN_STFS(fd, 0x16, PPC_FLOAT);
2831/* stfs stfsu stfsux stfsx */
2832GEN_STFS(fs, 0x14, PPC_FLOAT);
2833
2834/* Optional: */
2835/* stfiwx */
2836OP_ST_TABLE(fiw);
2837GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
2838
2839/*** Branch ***/
2840static always_inline void gen_goto_tb (DisasContext *ctx, int n,
2841 target_ulong dest)
2842{
2843 TranslationBlock *tb;
2844 tb = ctx->tb;
2845 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2846 likely(!ctx->singlestep_enabled)) {
2847 tcg_gen_goto_tb(n);
2848 tcg_gen_movi_tl(cpu_T[1], dest);
2849#if defined(TARGET_PPC64)
2850 if (ctx->sf_mode)
2851 tcg_gen_andi_tl(cpu_nip, cpu_T[1], ~3);
2852 else
2853#endif
2854 tcg_gen_andi_tl(cpu_nip, cpu_T[1], (uint32_t)~3);
2855 tcg_gen_exit_tb((long)tb + n);
2856 } else {
2857 tcg_gen_movi_tl(cpu_T[1], dest);
2858#if defined(TARGET_PPC64)
2859 if (ctx->sf_mode)
2860 tcg_gen_andi_tl(cpu_nip, cpu_T[1], ~3);
2861 else
2862#endif
2863 tcg_gen_andi_tl(cpu_nip, cpu_T[1], (uint32_t)~3);
2864 if (unlikely(ctx->singlestep_enabled)) {
2865 if ((ctx->singlestep_enabled &
2866 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
2867 ctx->exception == POWERPC_EXCP_BRANCH) {
2868 target_ulong tmp = ctx->nip;
2869 ctx->nip = dest;
2870 GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
2871 ctx->nip = tmp;
2872 }
2873 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
2874 gen_update_nip(ctx, dest);
2875 gen_op_debug();
2876 }
2877 }
2878 tcg_gen_exit_tb(0);
2879 }
2880}
2881
2882static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
2883{
2884#if defined(TARGET_PPC64)
2885 if (ctx->sf_mode != 0 && (nip >> 32))
2886 gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
2887 else
2888#endif
2889 gen_op_setlr(ctx->nip);
2890}
2891
2892/* b ba bl bla */
2893GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2894{
2895 target_ulong li, target;
2896
2897 ctx->exception = POWERPC_EXCP_BRANCH;
2898 /* sign extend LI */
2899#if defined(TARGET_PPC64)
2900 if (ctx->sf_mode)
2901 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
2902 else
2903#endif
2904 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
2905 if (likely(AA(ctx->opcode) == 0))
2906 target = ctx->nip + li - 4;
2907 else
2908 target = li;
2909#if defined(TARGET_PPC64)
2910 if (!ctx->sf_mode)
2911 target = (uint32_t)target;
2912#endif
2913 if (LK(ctx->opcode))
2914 gen_setlr(ctx, ctx->nip);
2915 gen_goto_tb(ctx, 0, target);
2916}
2917
2918#define BCOND_IM 0
2919#define BCOND_LR 1
2920#define BCOND_CTR 2
2921
2922static always_inline void gen_bcond (DisasContext *ctx, int type)
2923{
2924 target_ulong target = 0;
2925 target_ulong li;
2926 uint32_t bo = BO(ctx->opcode);
2927 uint32_t bi = BI(ctx->opcode);
2928 uint32_t mask;
2929
2930 ctx->exception = POWERPC_EXCP_BRANCH;
2931 if ((bo & 0x4) == 0)
2932 gen_op_dec_ctr();
2933 switch(type) {
2934 case BCOND_IM:
2935 li = (target_long)((int16_t)(BD(ctx->opcode)));
2936 if (likely(AA(ctx->opcode) == 0)) {
2937 target = ctx->nip + li - 4;
2938 } else {
2939 target = li;
2940 }
2941#if defined(TARGET_PPC64)
2942 if (!ctx->sf_mode)
2943 target = (uint32_t)target;
2944#endif
2945 break;
2946 case BCOND_CTR:
2947 gen_op_movl_T1_ctr();
2948 break;
2949 default:
2950 case BCOND_LR:
2951 gen_op_movl_T1_lr();
2952 break;
2953 }
2954 if (LK(ctx->opcode))
2955 gen_setlr(ctx, ctx->nip);
2956 if (bo & 0x10) {
2957 /* No CR condition */
2958 switch (bo & 0x6) {
2959 case 0:
2960#if defined(TARGET_PPC64)
2961 if (ctx->sf_mode)
2962 gen_op_test_ctr_64();
2963 else
2964#endif
2965 gen_op_test_ctr();
2966 break;
2967 case 2:
2968#if defined(TARGET_PPC64)
2969 if (ctx->sf_mode)
2970 gen_op_test_ctrz_64();
2971 else
2972#endif
2973 gen_op_test_ctrz();
2974 break;
2975 default:
2976 case 4:
2977 case 6:
2978 if (type == BCOND_IM) {
2979 gen_goto_tb(ctx, 0, target);
2980 return;
2981 } else {
2982#if defined(TARGET_PPC64)
2983 if (ctx->sf_mode)
2984 tcg_gen_andi_tl(cpu_nip, cpu_T[1], ~3);
2985 else
2986#endif
2987 tcg_gen_andi_tl(cpu_nip, cpu_T[1], (uint32_t)~3);
2988 goto no_test;
2989 }
2990 break;
2991 }
2992 } else {
2993 mask = 1 << (3 - (bi & 0x03));
2994 tcg_gen_mov_i32(cpu_T[0], cpu_crf[bi >> 2]);
2995 if (bo & 0x8) {
2996 switch (bo & 0x6) {
2997 case 0:
2998#if defined(TARGET_PPC64)
2999 if (ctx->sf_mode)
3000 gen_op_test_ctr_true_64(mask);
3001 else
3002#endif
3003 gen_op_test_ctr_true(mask);
3004 break;
3005 case 2:
3006#if defined(TARGET_PPC64)
3007 if (ctx->sf_mode)
3008 gen_op_test_ctrz_true_64(mask);
3009 else
3010#endif
3011 gen_op_test_ctrz_true(mask);
3012 break;
3013 default:
3014 case 4:
3015 case 6:
3016 gen_op_test_true(mask);
3017 break;
3018 }
3019 } else {
3020 switch (bo & 0x6) {
3021 case 0:
3022#if defined(TARGET_PPC64)
3023 if (ctx->sf_mode)
3024 gen_op_test_ctr_false_64(mask);
3025 else
3026#endif
3027 gen_op_test_ctr_false(mask);
3028 break;
3029 case 2:
3030#if defined(TARGET_PPC64)
3031 if (ctx->sf_mode)
3032 gen_op_test_ctrz_false_64(mask);
3033 else
3034#endif
3035 gen_op_test_ctrz_false(mask);
3036 break;
3037 default:
3038 case 4:
3039 case 6:
3040 gen_op_test_false(mask);
3041 break;
3042 }
3043 }
3044 }
3045 if (type == BCOND_IM) {
3046 int l1 = gen_new_label();
3047 gen_op_jz_T0(l1);
3048 gen_goto_tb(ctx, 0, target);
3049 gen_set_label(l1);
3050 gen_goto_tb(ctx, 1, ctx->nip);
3051 } else {
3052#if defined(TARGET_PPC64)
3053 if (ctx->sf_mode)
3054 gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
3055 else
3056#endif
3057 gen_op_btest_T1(ctx->nip);
3058 no_test:
3059 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3060 gen_update_nip(ctx, ctx->nip);
3061 gen_op_debug();
3062 }
3063 tcg_gen_exit_tb(0);
3064 }
3065}
3066
3067GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3068{
3069 gen_bcond(ctx, BCOND_IM);
3070}
3071
3072GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3073{
3074 gen_bcond(ctx, BCOND_CTR);
3075}
3076
3077GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3078{
3079 gen_bcond(ctx, BCOND_LR);
3080}
3081
3082/*** Condition register logical ***/
3083#define GEN_CRLOGIC(op, opc) \
3084GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
3085{ \
3086 uint8_t bitmask; \
3087 int sh; \
3088 tcg_gen_mov_i32(cpu_T[0], cpu_crf[crbA(ctx->opcode) >> 2]); \
3089 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
3090 if (sh > 0) \
3091 gen_op_srli_T0(sh); \
3092 else if (sh < 0) \
3093 gen_op_sli_T0(-sh); \
3094 tcg_gen_mov_i32(cpu_T[1], cpu_crf[crbB(ctx->opcode) >> 2]); \
3095 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3096 if (sh > 0) \
3097 gen_op_srli_T1(sh); \
3098 else if (sh < 0) \
3099 gen_op_sli_T1(-sh); \
3100 gen_op_##op(); \
3101 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
3102 gen_op_andi_T0(bitmask); \
3103 tcg_gen_andi_i32(cpu_T[1], cpu_crf[crbD(ctx->opcode) >> 2], ~bitmask); \
3104 gen_op_or(); \
3105 tcg_gen_andi_i32(cpu_crf[crbD(ctx->opcode) >> 2], cpu_T[0], 0xf); \
3106}
3107
3108/* crand */
3109GEN_CRLOGIC(and, 0x08);
3110/* crandc */
3111GEN_CRLOGIC(andc, 0x04);
3112/* creqv */
3113GEN_CRLOGIC(eqv, 0x09);
3114/* crnand */
3115GEN_CRLOGIC(nand, 0x07);
3116/* crnor */
3117GEN_CRLOGIC(nor, 0x01);
3118/* cror */
3119GEN_CRLOGIC(or, 0x0E);
3120/* crorc */
3121GEN_CRLOGIC(orc, 0x0D);
3122/* crxor */
3123GEN_CRLOGIC(xor, 0x06);
3124/* mcrf */
3125GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3126{
3127 tcg_gen_mov_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfS(ctx->opcode)]);
3128}
3129
3130/*** System linkage ***/
3131/* rfi (supervisor only) */
3132GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
3133{
3134#if defined(CONFIG_USER_ONLY)
3135 GEN_EXCP_PRIVOPC(ctx);
3136#else
3137 /* Restore CPU state */
3138 if (unlikely(!ctx->supervisor)) {
3139 GEN_EXCP_PRIVOPC(ctx);
3140 return;
3141 }
3142 gen_op_rfi();
3143 GEN_SYNC(ctx);
3144#endif
3145}
3146
3147#if defined(TARGET_PPC64)
3148GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3149{
3150#if defined(CONFIG_USER_ONLY)
3151 GEN_EXCP_PRIVOPC(ctx);
3152#else
3153 /* Restore CPU state */
3154 if (unlikely(!ctx->supervisor)) {
3155 GEN_EXCP_PRIVOPC(ctx);
3156 return;
3157 }
3158 gen_op_rfid();
3159 GEN_SYNC(ctx);
3160#endif
3161}
3162
3163GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3164{
3165#if defined(CONFIG_USER_ONLY)
3166 GEN_EXCP_PRIVOPC(ctx);
3167#else
3168 /* Restore CPU state */
3169 if (unlikely(ctx->supervisor <= 1)) {
3170 GEN_EXCP_PRIVOPC(ctx);
3171 return;
3172 }
3173 gen_op_hrfid();
3174 GEN_SYNC(ctx);
3175#endif
3176}
3177#endif
3178
3179/* sc */
3180#if defined(CONFIG_USER_ONLY)
3181#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3182#else
3183#define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3184#endif
3185GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3186{
3187 uint32_t lev;
3188
3189 lev = (ctx->opcode >> 5) & 0x7F;
3190 GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
3191}
3192
3193/*** Trap ***/
3194/* tw */
3195GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
3196{
3197 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3198 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3199 /* Update the nip since this might generate a trap exception */
3200 gen_update_nip(ctx, ctx->nip);
3201 gen_op_tw(TO(ctx->opcode));
3202}
3203
3204/* twi */
3205GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3206{
3207 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3208 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3209 /* Update the nip since this might generate a trap exception */
3210 gen_update_nip(ctx, ctx->nip);
3211 gen_op_tw(TO(ctx->opcode));
3212}
3213
3214#if defined(TARGET_PPC64)
3215/* td */
3216GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3217{
3218 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3219 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3220 /* Update the nip since this might generate a trap exception */
3221 gen_update_nip(ctx, ctx->nip);
3222 gen_op_td(TO(ctx->opcode));
3223}
3224
3225/* tdi */
3226GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3227{
3228 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3229 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3230 /* Update the nip since this might generate a trap exception */
3231 gen_update_nip(ctx, ctx->nip);
3232 gen_op_td(TO(ctx->opcode));
3233}
3234#endif
3235
3236/*** Processor control ***/
3237/* mcrxr */
3238GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3239{
3240 gen_op_load_xer_cr();
3241 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf);
3242 gen_op_clear_xer_ov();
3243 gen_op_clear_xer_ca();
3244}
3245
3246/* mfcr */
3247GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
3248{
3249 uint32_t crm, crn;
3250
3251 if (likely(ctx->opcode & 0x00100000)) {
3252 crm = CRM(ctx->opcode);
3253 if (likely((crm ^ (crm - 1)) == 0)) {
3254 crn = ffs(crm);
3255 tcg_gen_mov_i32(cpu_T[0], cpu_crf[7 - crn]);
3256 }
3257 } else {
3258 gen_op_load_cr();
3259 }
3260 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3261}
3262
3263/* mfmsr */
3264GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3265{
3266#if defined(CONFIG_USER_ONLY)
3267 GEN_EXCP_PRIVREG(ctx);
3268#else
3269 if (unlikely(!ctx->supervisor)) {
3270 GEN_EXCP_PRIVREG(ctx);
3271 return;
3272 }
3273 gen_op_load_msr();
3274 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3275#endif
3276}
3277
3278#if 1
3279#define SPR_NOACCESS ((void *)(-1UL))
3280#else
3281static void spr_noaccess (void *opaque, int sprn)
3282{
3283 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3284 printf("ERROR: try to access SPR %d !\n", sprn);
3285}
3286#define SPR_NOACCESS (&spr_noaccess)
3287#endif
3288
3289/* mfspr */
3290static always_inline void gen_op_mfspr (DisasContext *ctx)
3291{
3292 void (*read_cb)(void *opaque, int sprn);
3293 uint32_t sprn = SPR(ctx->opcode);
3294
3295#if !defined(CONFIG_USER_ONLY)
3296 if (ctx->supervisor == 2)
3297 read_cb = ctx->spr_cb[sprn].hea_read;
3298 else if (ctx->supervisor)
3299 read_cb = ctx->spr_cb[sprn].oea_read;
3300 else
3301#endif
3302 read_cb = ctx->spr_cb[sprn].uea_read;
3303 if (likely(read_cb != NULL)) {
3304 if (likely(read_cb != SPR_NOACCESS)) {
3305 (*read_cb)(ctx, sprn);
3306 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3307 } else {
3308 /* Privilege exception */
3309 /* This is a hack to avoid warnings when running Linux:
3310 * this OS breaks the PowerPC virtualisation model,
3311 * allowing userland application to read the PVR
3312 */
3313 if (sprn != SPR_PVR) {
3314 if (loglevel != 0) {
3315 fprintf(logfile, "Trying to read privileged spr %d %03x at "
3316 ADDRX "\n", sprn, sprn, ctx->nip);
3317 }
3318 printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3319 sprn, sprn, ctx->nip);
3320 }
3321 GEN_EXCP_PRIVREG(ctx);
3322 }
3323 } else {
3324 /* Not defined */
3325 if (loglevel != 0) {
3326 fprintf(logfile, "Trying to read invalid spr %d %03x at "
3327 ADDRX "\n", sprn, sprn, ctx->nip);
3328 }
3329 printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3330 sprn, sprn, ctx->nip);
3331 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3332 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3333 }
3334}
3335
3336GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3337{
3338 gen_op_mfspr(ctx);
3339}
3340
3341/* mftb */
3342GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3343{
3344 gen_op_mfspr(ctx);
3345}
3346
3347/* mtcrf */
3348GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3349{
3350 uint32_t crm, crn;
3351
3352 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3353 crm = CRM(ctx->opcode);
3354 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3355 crn = ffs(crm);
3356 gen_op_srli_T0(crn * 4);
3357 tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_T[0], 0xf);
3358 } else {
3359 gen_op_store_cr(crm);
3360 }
3361}
3362
3363/* mtmsr */
3364#if defined(TARGET_PPC64)
3365GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3366{
3367#if defined(CONFIG_USER_ONLY)
3368 GEN_EXCP_PRIVREG(ctx);
3369#else
3370 if (unlikely(!ctx->supervisor)) {
3371 GEN_EXCP_PRIVREG(ctx);
3372 return;
3373 }
3374 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3375 if (ctx->opcode & 0x00010000) {
3376 /* Special form that does not need any synchronisation */
3377 gen_op_update_riee();
3378 } else {
3379 /* XXX: we need to update nip before the store
3380 * if we enter power saving mode, we will exit the loop
3381 * directly from ppc_store_msr
3382 */
3383 gen_update_nip(ctx, ctx->nip);
3384 gen_op_store_msr();
3385 /* Must stop the translation as machine state (may have) changed */
3386 /* Note that mtmsr is not always defined as context-synchronizing */
3387 ctx->exception = POWERPC_EXCP_STOP;
3388 }
3389#endif
3390}
3391#endif
3392
3393GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3394{
3395#if defined(CONFIG_USER_ONLY)
3396 GEN_EXCP_PRIVREG(ctx);
3397#else
3398 if (unlikely(!ctx->supervisor)) {
3399 GEN_EXCP_PRIVREG(ctx);
3400 return;
3401 }
3402 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3403 if (ctx->opcode & 0x00010000) {
3404 /* Special form that does not need any synchronisation */
3405 gen_op_update_riee();
3406 } else {
3407 /* XXX: we need to update nip before the store
3408 * if we enter power saving mode, we will exit the loop
3409 * directly from ppc_store_msr
3410 */
3411 gen_update_nip(ctx, ctx->nip);
3412#if defined(TARGET_PPC64)
3413 if (!ctx->sf_mode)
3414 gen_op_store_msr_32();
3415 else
3416#endif
3417 gen_op_store_msr();
3418 /* Must stop the translation as machine state (may have) changed */
3419 /* Note that mtmsrd is not always defined as context-synchronizing */
3420 ctx->exception = POWERPC_EXCP_STOP;
3421 }
3422#endif
3423}
3424
3425/* mtspr */
3426GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3427{
3428 void (*write_cb)(void *opaque, int sprn);
3429 uint32_t sprn = SPR(ctx->opcode);
3430
3431#if !defined(CONFIG_USER_ONLY)
3432 if (ctx->supervisor == 2)
3433 write_cb = ctx->spr_cb[sprn].hea_write;
3434 else if (ctx->supervisor)
3435 write_cb = ctx->spr_cb[sprn].oea_write;
3436 else
3437#endif
3438 write_cb = ctx->spr_cb[sprn].uea_write;
3439 if (likely(write_cb != NULL)) {
3440 if (likely(write_cb != SPR_NOACCESS)) {
3441 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3442 (*write_cb)(ctx, sprn);
3443 } else {
3444 /* Privilege exception */
3445 if (loglevel != 0) {
3446 fprintf(logfile, "Trying to write privileged spr %d %03x at "
3447 ADDRX "\n", sprn, sprn, ctx->nip);
3448 }
3449 printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
3450 sprn, sprn, ctx->nip);
3451 GEN_EXCP_PRIVREG(ctx);
3452 }
3453 } else {
3454 /* Not defined */
3455 if (loglevel != 0) {
3456 fprintf(logfile, "Trying to write invalid spr %d %03x at "
3457 ADDRX "\n", sprn, sprn, ctx->nip);
3458 }
3459 printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
3460 sprn, sprn, ctx->nip);
3461 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3462 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3463 }
3464}
3465
3466/*** Cache management ***/
3467/* dcbf */
3468GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
3469{
3470 /* XXX: specification says this is treated as a load by the MMU */
3471 gen_addr_reg_index(ctx);
3472 op_ldst(lbz);
3473}
3474
3475/* dcbi (Supervisor only) */
3476GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
3477{
3478#if defined(CONFIG_USER_ONLY)
3479 GEN_EXCP_PRIVOPC(ctx);
3480#else
3481 if (unlikely(!ctx->supervisor)) {
3482 GEN_EXCP_PRIVOPC(ctx);
3483 return;
3484 }
3485 gen_addr_reg_index(ctx);
3486 /* XXX: specification says this should be treated as a store by the MMU */
3487 op_ldst(lbz);
3488 op_ldst(stb);
3489#endif
3490}
3491
3492/* dcdst */
3493GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
3494{
3495 /* XXX: specification say this is treated as a load by the MMU */
3496 gen_addr_reg_index(ctx);
3497 op_ldst(lbz);
3498}
3499
3500/* dcbt */
3501GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
3502{
3503 /* interpreted as no-op */
3504 /* XXX: specification say this is treated as a load by the MMU
3505 * but does not generate any exception
3506 */
3507}
3508
3509/* dcbtst */
3510GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
3511{
3512 /* interpreted as no-op */
3513 /* XXX: specification say this is treated as a load by the MMU
3514 * but does not generate any exception
3515 */
3516}
3517
3518/* dcbz */
3519#define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
3520static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
3521 /* 32 bytes cache line size */
3522 {
3523#define gen_op_dcbz_l32_le_raw gen_op_dcbz_l32_raw
3524#define gen_op_dcbz_l32_le_user gen_op_dcbz_l32_user
3525#define gen_op_dcbz_l32_le_kernel gen_op_dcbz_l32_kernel
3526#define gen_op_dcbz_l32_le_hypv gen_op_dcbz_l32_hypv
3527#define gen_op_dcbz_l32_le_64_raw gen_op_dcbz_l32_64_raw
3528#define gen_op_dcbz_l32_le_64_user gen_op_dcbz_l32_64_user
3529#define gen_op_dcbz_l32_le_64_kernel gen_op_dcbz_l32_64_kernel
3530#define gen_op_dcbz_l32_le_64_hypv gen_op_dcbz_l32_64_hypv
3531 GEN_MEM_FUNCS(dcbz_l32),
3532 },
3533 /* 64 bytes cache line size */
3534 {
3535#define gen_op_dcbz_l64_le_raw gen_op_dcbz_l64_raw
3536#define gen_op_dcbz_l64_le_user gen_op_dcbz_l64_user
3537#define gen_op_dcbz_l64_le_kernel gen_op_dcbz_l64_kernel
3538#define gen_op_dcbz_l64_le_hypv gen_op_dcbz_l64_hypv
3539#define gen_op_dcbz_l64_le_64_raw gen_op_dcbz_l64_64_raw
3540#define gen_op_dcbz_l64_le_64_user gen_op_dcbz_l64_64_user
3541#define gen_op_dcbz_l64_le_64_kernel gen_op_dcbz_l64_64_kernel
3542#define gen_op_dcbz_l64_le_64_hypv gen_op_dcbz_l64_64_hypv
3543 GEN_MEM_FUNCS(dcbz_l64),
3544 },
3545 /* 128 bytes cache line size */
3546 {
3547#define gen_op_dcbz_l128_le_raw gen_op_dcbz_l128_raw
3548#define gen_op_dcbz_l128_le_user gen_op_dcbz_l128_user
3549#define gen_op_dcbz_l128_le_kernel gen_op_dcbz_l128_kernel
3550#define gen_op_dcbz_l128_le_hypv gen_op_dcbz_l128_hypv
3551#define gen_op_dcbz_l128_le_64_raw gen_op_dcbz_l128_64_raw
3552#define gen_op_dcbz_l128_le_64_user gen_op_dcbz_l128_64_user
3553#define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
3554#define gen_op_dcbz_l128_le_64_hypv gen_op_dcbz_l128_64_hypv
3555 GEN_MEM_FUNCS(dcbz_l128),
3556 },
3557 /* tunable cache line size */
3558 {
3559#define gen_op_dcbz_le_raw gen_op_dcbz_raw
3560#define gen_op_dcbz_le_user gen_op_dcbz_user
3561#define gen_op_dcbz_le_kernel gen_op_dcbz_kernel
3562#define gen_op_dcbz_le_hypv gen_op_dcbz_hypv
3563#define gen_op_dcbz_le_64_raw gen_op_dcbz_64_raw
3564#define gen_op_dcbz_le_64_user gen_op_dcbz_64_user
3565#define gen_op_dcbz_le_64_kernel gen_op_dcbz_64_kernel
3566#define gen_op_dcbz_le_64_hypv gen_op_dcbz_64_hypv
3567 GEN_MEM_FUNCS(dcbz),
3568 },
3569};
3570
3571static always_inline void handler_dcbz (DisasContext *ctx,
3572 int dcache_line_size)
3573{
3574 int n;
3575
3576 switch (dcache_line_size) {
3577 case 32:
3578 n = 0;
3579 break;
3580 case 64:
3581 n = 1;
3582 break;
3583 case 128:
3584 n = 2;
3585 break;
3586 default:
3587 n = 3;
3588 break;
3589 }
3590 op_dcbz(n);
3591}
3592
3593GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
3594{
3595 gen_addr_reg_index(ctx);
3596 handler_dcbz(ctx, ctx->dcache_line_size);
3597 gen_op_check_reservation();
3598}
3599
3600GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3601{
3602 gen_addr_reg_index(ctx);
3603 if (ctx->opcode & 0x00200000)
3604 handler_dcbz(ctx, ctx->dcache_line_size);
3605 else
3606 handler_dcbz(ctx, -1);
3607 gen_op_check_reservation();
3608}
3609
3610/* icbi */
3611#define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3612#define gen_op_icbi_le_raw gen_op_icbi_raw
3613#define gen_op_icbi_le_user gen_op_icbi_user
3614#define gen_op_icbi_le_kernel gen_op_icbi_kernel
3615#define gen_op_icbi_le_hypv gen_op_icbi_hypv
3616#define gen_op_icbi_le_64_raw gen_op_icbi_64_raw
3617#define gen_op_icbi_le_64_user gen_op_icbi_64_user
3618#define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
3619#define gen_op_icbi_le_64_hypv gen_op_icbi_64_hypv
3620static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
3621 GEN_MEM_FUNCS(icbi),
3622};
3623
3624GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
3625{
3626 /* NIP cannot be restored if the memory exception comes from an helper */
3627 gen_update_nip(ctx, ctx->nip - 4);
3628 gen_addr_reg_index(ctx);
3629 op_icbi();
3630}
3631
3632/* Optional: */
3633/* dcba */
3634GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
3635{
3636 /* interpreted as no-op */
3637 /* XXX: specification say this is treated as a store by the MMU
3638 * but does not generate any exception
3639 */
3640}
3641
3642/*** Segment register manipulation ***/
3643/* Supervisor only: */
3644/* mfsr */
3645GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3646{
3647#if defined(CONFIG_USER_ONLY)
3648 GEN_EXCP_PRIVREG(ctx);
3649#else
3650 if (unlikely(!ctx->supervisor)) {
3651 GEN_EXCP_PRIVREG(ctx);
3652 return;
3653 }
3654 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3655 gen_op_load_sr();
3656 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3657#endif
3658}
3659
3660/* mfsrin */
3661GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
3662{
3663#if defined(CONFIG_USER_ONLY)
3664 GEN_EXCP_PRIVREG(ctx);
3665#else
3666 if (unlikely(!ctx->supervisor)) {
3667 GEN_EXCP_PRIVREG(ctx);
3668 return;
3669 }
3670 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3671 gen_op_srli_T1(28);
3672 gen_op_load_sr();
3673 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3674#endif
3675}
3676
3677/* mtsr */
3678GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
3679{
3680#if defined(CONFIG_USER_ONLY)
3681 GEN_EXCP_PRIVREG(ctx);
3682#else
3683 if (unlikely(!ctx->supervisor)) {
3684 GEN_EXCP_PRIVREG(ctx);
3685 return;
3686 }
3687 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3688 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3689 gen_op_store_sr();
3690#endif
3691}
3692
3693/* mtsrin */
3694GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
3695{
3696#if defined(CONFIG_USER_ONLY)
3697 GEN_EXCP_PRIVREG(ctx);
3698#else
3699 if (unlikely(!ctx->supervisor)) {
3700 GEN_EXCP_PRIVREG(ctx);
3701 return;
3702 }
3703 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3704 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3705 gen_op_srli_T1(28);
3706 gen_op_store_sr();
3707#endif
3708}
3709
3710#if defined(TARGET_PPC64)
3711/* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
3712/* mfsr */
3713GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
3714{
3715#if defined(CONFIG_USER_ONLY)
3716 GEN_EXCP_PRIVREG(ctx);
3717#else
3718 if (unlikely(!ctx->supervisor)) {
3719 GEN_EXCP_PRIVREG(ctx);
3720 return;
3721 }
3722 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3723 gen_op_load_slb();
3724 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3725#endif
3726}
3727
3728/* mfsrin */
3729GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
3730 PPC_SEGMENT_64B)
3731{
3732#if defined(CONFIG_USER_ONLY)
3733 GEN_EXCP_PRIVREG(ctx);
3734#else
3735 if (unlikely(!ctx->supervisor)) {
3736 GEN_EXCP_PRIVREG(ctx);
3737 return;
3738 }
3739 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3740 gen_op_srli_T1(28);
3741 gen_op_load_slb();
3742 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3743#endif
3744}
3745
3746/* mtsr */
3747GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
3748{
3749#if defined(CONFIG_USER_ONLY)
3750 GEN_EXCP_PRIVREG(ctx);
3751#else
3752 if (unlikely(!ctx->supervisor)) {
3753 GEN_EXCP_PRIVREG(ctx);
3754 return;
3755 }
3756 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3757 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3758 gen_op_store_slb();
3759#endif
3760}
3761
3762/* mtsrin */
3763GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
3764 PPC_SEGMENT_64B)
3765{
3766#if defined(CONFIG_USER_ONLY)
3767 GEN_EXCP_PRIVREG(ctx);
3768#else
3769 if (unlikely(!ctx->supervisor)) {
3770 GEN_EXCP_PRIVREG(ctx);
3771 return;
3772 }
3773 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3774 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3775 gen_op_srli_T1(28);
3776 gen_op_store_slb();
3777#endif
3778}
3779#endif /* defined(TARGET_PPC64) */
3780
3781/*** Lookaside buffer management ***/
3782/* Optional & supervisor only: */
3783/* tlbia */
3784GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
3785{
3786#if defined(CONFIG_USER_ONLY)
3787 GEN_EXCP_PRIVOPC(ctx);
3788#else
3789 if (unlikely(!ctx->supervisor)) {
3790 GEN_EXCP_PRIVOPC(ctx);
3791 return;
3792 }
3793 gen_op_tlbia();
3794#endif
3795}
3796
3797/* tlbie */
3798GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
3799{
3800#if defined(CONFIG_USER_ONLY)
3801 GEN_EXCP_PRIVOPC(ctx);
3802#else
3803 if (unlikely(!ctx->supervisor)) {
3804 GEN_EXCP_PRIVOPC(ctx);
3805 return;
3806 }
3807 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
3808#if defined(TARGET_PPC64)
3809 if (ctx->sf_mode)
3810 gen_op_tlbie_64();
3811 else
3812#endif
3813 gen_op_tlbie();
3814#endif
3815}
3816
3817/* tlbsync */
3818GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
3819{
3820#if defined(CONFIG_USER_ONLY)
3821 GEN_EXCP_PRIVOPC(ctx);
3822#else
3823 if (unlikely(!ctx->supervisor)) {
3824 GEN_EXCP_PRIVOPC(ctx);
3825 return;
3826 }
3827 /* This has no effect: it should ensure that all previous
3828 * tlbie have completed
3829 */
3830 GEN_STOP(ctx);
3831#endif
3832}
3833
3834#if defined(TARGET_PPC64)
3835/* slbia */
3836GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
3837{
3838#if defined(CONFIG_USER_ONLY)
3839 GEN_EXCP_PRIVOPC(ctx);
3840#else
3841 if (unlikely(!ctx->supervisor)) {
3842 GEN_EXCP_PRIVOPC(ctx);
3843 return;
3844 }
3845 gen_op_slbia();
3846#endif
3847}
3848
3849/* slbie */
3850GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
3851{
3852#if defined(CONFIG_USER_ONLY)
3853 GEN_EXCP_PRIVOPC(ctx);
3854#else
3855 if (unlikely(!ctx->supervisor)) {
3856 GEN_EXCP_PRIVOPC(ctx);
3857 return;
3858 }
3859 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
3860 gen_op_slbie();
3861#endif
3862}
3863#endif
3864
3865/*** External control ***/
3866/* Optional: */
3867#define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
3868#define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3869static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
3870 GEN_MEM_FUNCS(eciwx),
3871};
3872static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
3873 GEN_MEM_FUNCS(ecowx),
3874};
3875
3876/* eciwx */
3877GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
3878{
3879 /* Should check EAR[E] & alignment ! */
3880 gen_addr_reg_index(ctx);
3881 op_eciwx();
3882 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3883}
3884
3885/* ecowx */
3886GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
3887{
3888 /* Should check EAR[E] & alignment ! */
3889 gen_addr_reg_index(ctx);
3890 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
3891 op_ecowx();
3892}
3893
3894/* PowerPC 601 specific instructions */
3895/* abs - abs. */
3896GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
3897{
3898 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3899 gen_op_POWER_abs();
3900 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3901 if (unlikely(Rc(ctx->opcode) != 0))
3902 gen_set_Rc0(ctx);
3903}
3904
3905/* abso - abso. */
3906GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
3907{
3908 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3909 gen_op_POWER_abso();
3910 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3911 if (unlikely(Rc(ctx->opcode) != 0))
3912 gen_set_Rc0(ctx);
3913}
3914
3915/* clcs */
3916GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
3917{
3918 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3919 gen_op_POWER_clcs();
3920 /* Rc=1 sets CR0 to an undefined state */
3921 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3922}
3923
3924/* div - div. */
3925GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
3926{
3927 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3928 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3929 gen_op_POWER_div();
3930 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3931 if (unlikely(Rc(ctx->opcode) != 0))
3932 gen_set_Rc0(ctx);
3933}
3934
3935/* divo - divo. */
3936GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
3937{
3938 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3939 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3940 gen_op_POWER_divo();
3941 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3942 if (unlikely(Rc(ctx->opcode) != 0))
3943 gen_set_Rc0(ctx);
3944}
3945
3946/* divs - divs. */
3947GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
3948{
3949 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3950 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3951 gen_op_POWER_divs();
3952 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3953 if (unlikely(Rc(ctx->opcode) != 0))
3954 gen_set_Rc0(ctx);
3955}
3956
3957/* divso - divso. */
3958GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
3959{
3960 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3961 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3962 gen_op_POWER_divso();
3963 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3964 if (unlikely(Rc(ctx->opcode) != 0))
3965 gen_set_Rc0(ctx);
3966}
3967
3968/* doz - doz. */
3969GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
3970{
3971 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3972 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3973 gen_op_POWER_doz();
3974 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3975 if (unlikely(Rc(ctx->opcode) != 0))
3976 gen_set_Rc0(ctx);
3977}
3978
3979/* dozo - dozo. */
3980GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
3981{
3982 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3983 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3984 gen_op_POWER_dozo();
3985 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3986 if (unlikely(Rc(ctx->opcode) != 0))
3987 gen_set_Rc0(ctx);
3988}
3989
3990/* dozi */
3991GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
3992{
3993 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3994 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3995 gen_op_POWER_doz();
3996 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3997}
3998
3999/* As lscbx load from memory byte after byte, it's always endian safe.
4000 * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
4001 */
4002#define op_POWER_lscbx(start, ra, rb) \
4003(*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4004#define gen_op_POWER_lscbx_64_raw gen_op_POWER_lscbx_raw
4005#define gen_op_POWER_lscbx_64_user gen_op_POWER_lscbx_user
4006#define gen_op_POWER_lscbx_64_kernel gen_op_POWER_lscbx_kernel
4007#define gen_op_POWER_lscbx_64_hypv gen_op_POWER_lscbx_hypv
4008#define gen_op_POWER_lscbx_le_raw gen_op_POWER_lscbx_raw
4009#define gen_op_POWER_lscbx_le_user gen_op_POWER_lscbx_user
4010#define gen_op_POWER_lscbx_le_kernel gen_op_POWER_lscbx_kernel
4011#define gen_op_POWER_lscbx_le_hypv gen_op_POWER_lscbx_hypv
4012#define gen_op_POWER_lscbx_le_64_raw gen_op_POWER_lscbx_raw
4013#define gen_op_POWER_lscbx_le_64_user gen_op_POWER_lscbx_user
4014#define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
4015#define gen_op_POWER_lscbx_le_64_hypv gen_op_POWER_lscbx_hypv
4016static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
4017 GEN_MEM_FUNCS(POWER_lscbx),
4018};
4019
4020/* lscbx - lscbx. */
4021GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4022{
4023 int ra = rA(ctx->opcode);
4024 int rb = rB(ctx->opcode);
4025
4026 gen_addr_reg_index(ctx);
4027 if (ra == 0) {
4028 ra = rb;
4029 }
4030 /* NIP cannot be restored if the memory exception comes from an helper */
4031 gen_update_nip(ctx, ctx->nip - 4);
4032 gen_op_load_xer_bc();
4033 gen_op_load_xer_cmp();
4034 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
4035 gen_op_store_xer_bc();
4036 if (unlikely(Rc(ctx->opcode) != 0))
4037 gen_set_Rc0(ctx);
4038}
4039
4040/* maskg - maskg. */
4041GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4042{
4043 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4044 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4045 gen_op_POWER_maskg();
4046 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4047 if (unlikely(Rc(ctx->opcode) != 0))
4048 gen_set_Rc0(ctx);
4049}
4050
4051/* maskir - maskir. */
4052GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4053{
4054 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4055 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4056 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4057 gen_op_POWER_maskir();
4058 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4059 if (unlikely(Rc(ctx->opcode) != 0))
4060 gen_set_Rc0(ctx);
4061}
4062
4063/* mul - mul. */
4064GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4065{
4066 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4067 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4068 gen_op_POWER_mul();
4069 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4070 if (unlikely(Rc(ctx->opcode) != 0))
4071 gen_set_Rc0(ctx);
4072}
4073
4074/* mulo - mulo. */
4075GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4076{
4077 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4078 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4079 gen_op_POWER_mulo();
4080 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4081 if (unlikely(Rc(ctx->opcode) != 0))
4082 gen_set_Rc0(ctx);
4083}
4084
4085/* nabs - nabs. */
4086GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4087{
4088 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4089 gen_op_POWER_nabs();
4090 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4091 if (unlikely(Rc(ctx->opcode) != 0))
4092 gen_set_Rc0(ctx);
4093}
4094
4095/* nabso - nabso. */
4096GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4097{
4098 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4099 gen_op_POWER_nabso();
4100 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4101 if (unlikely(Rc(ctx->opcode) != 0))
4102 gen_set_Rc0(ctx);
4103}
4104
4105/* rlmi - rlmi. */
4106GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4107{
4108 uint32_t mb, me;
4109
4110 mb = MB(ctx->opcode);
4111 me = ME(ctx->opcode);
4112 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4113 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4114 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4115 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
4116 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4117 if (unlikely(Rc(ctx->opcode) != 0))
4118 gen_set_Rc0(ctx);
4119}
4120
4121/* rrib - rrib. */
4122GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4123{
4124 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4125 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4126 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4127 gen_op_POWER_rrib();
4128 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4129 if (unlikely(Rc(ctx->opcode) != 0))
4130 gen_set_Rc0(ctx);
4131}
4132
4133/* sle - sle. */
4134GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4135{
4136 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4137 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4138 gen_op_POWER_sle();
4139 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4140 if (unlikely(Rc(ctx->opcode) != 0))
4141 gen_set_Rc0(ctx);
4142}
4143
4144/* sleq - sleq. */
4145GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4146{
4147 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4148 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4149 gen_op_POWER_sleq();
4150 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4151 if (unlikely(Rc(ctx->opcode) != 0))
4152 gen_set_Rc0(ctx);
4153}
4154
4155/* sliq - sliq. */
4156GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4157{
4158 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4159 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4160 gen_op_POWER_sle();
4161 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4162 if (unlikely(Rc(ctx->opcode) != 0))
4163 gen_set_Rc0(ctx);
4164}
4165
4166/* slliq - slliq. */
4167GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4168{
4169 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4170 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4171 gen_op_POWER_sleq();
4172 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4173 if (unlikely(Rc(ctx->opcode) != 0))
4174 gen_set_Rc0(ctx);
4175}
4176
4177/* sllq - sllq. */
4178GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4179{
4180 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4181 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4182 gen_op_POWER_sllq();
4183 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4184 if (unlikely(Rc(ctx->opcode) != 0))
4185 gen_set_Rc0(ctx);
4186}
4187
4188/* slq - slq. */
4189GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4190{
4191 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4192 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4193 gen_op_POWER_slq();
4194 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4195 if (unlikely(Rc(ctx->opcode) != 0))
4196 gen_set_Rc0(ctx);
4197}
4198
4199/* sraiq - sraiq. */
4200GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4201{
4202 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4203 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4204 gen_op_POWER_sraq();
4205 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4206 if (unlikely(Rc(ctx->opcode) != 0))
4207 gen_set_Rc0(ctx);
4208}
4209
4210/* sraq - sraq. */
4211GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4212{
4213 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4214 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4215 gen_op_POWER_sraq();
4216 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4217 if (unlikely(Rc(ctx->opcode) != 0))
4218 gen_set_Rc0(ctx);
4219}
4220
4221/* sre - sre. */
4222GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4223{
4224 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4225 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4226 gen_op_POWER_sre();
4227 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4228 if (unlikely(Rc(ctx->opcode) != 0))
4229 gen_set_Rc0(ctx);
4230}
4231
4232/* srea - srea. */
4233GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4234{
4235 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4236 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4237 gen_op_POWER_srea();
4238 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4239 if (unlikely(Rc(ctx->opcode) != 0))
4240 gen_set_Rc0(ctx);
4241}
4242
4243/* sreq */
4244GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4245{
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)]);
4248 gen_op_POWER_sreq();
4249 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4250 if (unlikely(Rc(ctx->opcode) != 0))
4251 gen_set_Rc0(ctx);
4252}
4253
4254/* sriq */
4255GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4256{
4257 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4258 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4259 gen_op_POWER_srq();
4260 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4261 if (unlikely(Rc(ctx->opcode) != 0))
4262 gen_set_Rc0(ctx);
4263}
4264
4265/* srliq */
4266GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4267{
4268 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4269 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4270 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4271 gen_op_POWER_srlq();
4272 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4273 if (unlikely(Rc(ctx->opcode) != 0))
4274 gen_set_Rc0(ctx);
4275}
4276
4277/* srlq */
4278GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
4279{
4280 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4281 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4282 gen_op_POWER_srlq();
4283 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4284 if (unlikely(Rc(ctx->opcode) != 0))
4285 gen_set_Rc0(ctx);
4286}
4287
4288/* srq */
4289GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
4290{
4291 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4292 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4293 gen_op_POWER_srq();
4294 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4295 if (unlikely(Rc(ctx->opcode) != 0))
4296 gen_set_Rc0(ctx);
4297}
4298
4299/* PowerPC 602 specific instructions */
4300/* dsa */
4301GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
4302{
4303 /* XXX: TODO */
4304 GEN_EXCP_INVAL(ctx);
4305}
4306
4307/* esa */
4308GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
4309{
4310 /* XXX: TODO */
4311 GEN_EXCP_INVAL(ctx);
4312}
4313
4314/* mfrom */
4315GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4316{
4317#if defined(CONFIG_USER_ONLY)
4318 GEN_EXCP_PRIVOPC(ctx);
4319#else
4320 if (unlikely(!ctx->supervisor)) {
4321 GEN_EXCP_PRIVOPC(ctx);
4322 return;
4323 }
4324 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4325 gen_op_602_mfrom();
4326 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4327#endif
4328}
4329
4330/* 602 - 603 - G2 TLB management */
4331/* tlbld */
4332GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4333{
4334#if defined(CONFIG_USER_ONLY)
4335 GEN_EXCP_PRIVOPC(ctx);
4336#else
4337 if (unlikely(!ctx->supervisor)) {
4338 GEN_EXCP_PRIVOPC(ctx);
4339 return;
4340 }
4341 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4342 gen_op_6xx_tlbld();
4343#endif
4344}
4345
4346/* tlbli */
4347GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4348{
4349#if defined(CONFIG_USER_ONLY)
4350 GEN_EXCP_PRIVOPC(ctx);
4351#else
4352 if (unlikely(!ctx->supervisor)) {
4353 GEN_EXCP_PRIVOPC(ctx);
4354 return;
4355 }
4356 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4357 gen_op_6xx_tlbli();
4358#endif
4359}
4360
4361/* 74xx TLB management */
4362/* tlbld */
4363GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4364{
4365#if defined(CONFIG_USER_ONLY)
4366 GEN_EXCP_PRIVOPC(ctx);
4367#else
4368 if (unlikely(!ctx->supervisor)) {
4369 GEN_EXCP_PRIVOPC(ctx);
4370 return;
4371 }
4372 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4373 gen_op_74xx_tlbld();
4374#endif
4375}
4376
4377/* tlbli */
4378GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4379{
4380#if defined(CONFIG_USER_ONLY)
4381 GEN_EXCP_PRIVOPC(ctx);
4382#else
4383 if (unlikely(!ctx->supervisor)) {
4384 GEN_EXCP_PRIVOPC(ctx);
4385 return;
4386 }
4387 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4388 gen_op_74xx_tlbli();
4389#endif
4390}
4391
4392/* POWER instructions not in PowerPC 601 */
4393/* clf */
4394GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
4395{
4396 /* Cache line flush: implemented as no-op */
4397}
4398
4399/* cli */
4400GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
4401{
4402 /* Cache line invalidate: privileged and treated as no-op */
4403#if defined(CONFIG_USER_ONLY)
4404 GEN_EXCP_PRIVOPC(ctx);
4405#else
4406 if (unlikely(!ctx->supervisor)) {
4407 GEN_EXCP_PRIVOPC(ctx);
4408 return;
4409 }
4410#endif
4411}
4412
4413/* dclst */
4414GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
4415{
4416 /* Data cache line store: treated as no-op */
4417}
4418
4419GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
4420{
4421#if defined(CONFIG_USER_ONLY)
4422 GEN_EXCP_PRIVOPC(ctx);
4423#else
4424 if (unlikely(!ctx->supervisor)) {
4425 GEN_EXCP_PRIVOPC(ctx);
4426 return;
4427 }
4428 int ra = rA(ctx->opcode);
4429 int rd = rD(ctx->opcode);
4430
4431 gen_addr_reg_index(ctx);
4432 gen_op_POWER_mfsri();
4433 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
4434 if (ra != 0 && ra != rd)
4435 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
4436#endif
4437}
4438
4439GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
4440{
4441#if defined(CONFIG_USER_ONLY)
4442 GEN_EXCP_PRIVOPC(ctx);
4443#else
4444 if (unlikely(!ctx->supervisor)) {
4445 GEN_EXCP_PRIVOPC(ctx);
4446 return;
4447 }
4448 gen_addr_reg_index(ctx);
4449 gen_op_POWER_rac();
4450 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4451#endif
4452}
4453
4454GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
4455{
4456#if defined(CONFIG_USER_ONLY)
4457 GEN_EXCP_PRIVOPC(ctx);
4458#else
4459 if (unlikely(!ctx->supervisor)) {
4460 GEN_EXCP_PRIVOPC(ctx);
4461 return;
4462 }
4463 gen_op_POWER_rfsvc();
4464 GEN_SYNC(ctx);
4465#endif
4466}
4467
4468/* svc is not implemented for now */
4469
4470/* POWER2 specific instructions */
4471/* Quad manipulation (load/store two floats at a time) */
4472/* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
4473#define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4474#define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4475#define gen_op_POWER2_lfq_64_raw gen_op_POWER2_lfq_raw
4476#define gen_op_POWER2_lfq_64_user gen_op_POWER2_lfq_user
4477#define gen_op_POWER2_lfq_64_kernel gen_op_POWER2_lfq_kernel
4478#define gen_op_POWER2_lfq_64_hypv gen_op_POWER2_lfq_hypv
4479#define gen_op_POWER2_lfq_le_64_raw gen_op_POWER2_lfq_le_raw
4480#define gen_op_POWER2_lfq_le_64_user gen_op_POWER2_lfq_le_user
4481#define gen_op_POWER2_lfq_le_64_kernel gen_op_POWER2_lfq_le_kernel
4482#define gen_op_POWER2_lfq_le_64_hypv gen_op_POWER2_lfq_le_hypv
4483#define gen_op_POWER2_stfq_64_raw gen_op_POWER2_stfq_raw
4484#define gen_op_POWER2_stfq_64_user gen_op_POWER2_stfq_user
4485#define gen_op_POWER2_stfq_64_kernel gen_op_POWER2_stfq_kernel
4486#define gen_op_POWER2_stfq_64_hypv gen_op_POWER2_stfq_hypv
4487#define gen_op_POWER2_stfq_le_64_raw gen_op_POWER2_stfq_le_raw
4488#define gen_op_POWER2_stfq_le_64_user gen_op_POWER2_stfq_le_user
4489#define gen_op_POWER2_stfq_le_64_kernel gen_op_POWER2_stfq_le_kernel
4490#define gen_op_POWER2_stfq_le_64_hypv gen_op_POWER2_stfq_le_hypv
4491static GenOpFunc *gen_op_POWER2_lfq[NB_MEM_FUNCS] = {
4492 GEN_MEM_FUNCS(POWER2_lfq),
4493};
4494static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
4495 GEN_MEM_FUNCS(POWER2_stfq),
4496};
4497
4498/* lfq */
4499GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4500{
4501 /* NIP cannot be restored if the memory exception comes from an helper */
4502 gen_update_nip(ctx, ctx->nip - 4);
4503 gen_addr_imm_index(ctx, 0);
4504 op_POWER2_lfq();
4505 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
4506 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4507}
4508
4509/* lfqu */
4510GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4511{
4512 int ra = rA(ctx->opcode);
4513
4514 /* NIP cannot be restored if the memory exception comes from an helper */
4515 gen_update_nip(ctx, ctx->nip - 4);
4516 gen_addr_imm_index(ctx, 0);
4517 op_POWER2_lfq();
4518 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
4519 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4520 if (ra != 0)
4521 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4522}
4523
4524/* lfqux */
4525GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
4526{
4527 int ra = rA(ctx->opcode);
4528
4529 /* NIP cannot be restored if the memory exception comes from an helper */
4530 gen_update_nip(ctx, ctx->nip - 4);
4531 gen_addr_reg_index(ctx);
4532 op_POWER2_lfq();
4533 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
4534 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4535 if (ra != 0)
4536 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4537}
4538
4539/* lfqx */
4540GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
4541{
4542 /* NIP cannot be restored if the memory exception comes from an helper */
4543 gen_update_nip(ctx, ctx->nip - 4);
4544 gen_addr_reg_index(ctx);
4545 op_POWER2_lfq();
4546 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode)], cpu_FT[0]);
4547 tcg_gen_mov_i64(cpu_fpr[rD(ctx->opcode) + 1], cpu_FT[1]);
4548}
4549
4550/* stfq */
4551GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4552{
4553 /* NIP cannot be restored if the memory exception comes from an helper */
4554 gen_update_nip(ctx, ctx->nip - 4);
4555 gen_addr_imm_index(ctx, 0);
4556 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
4557 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4558 op_POWER2_stfq();
4559}
4560
4561/* stfqu */
4562GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4563{
4564 int ra = rA(ctx->opcode);
4565
4566 /* NIP cannot be restored if the memory exception comes from an helper */
4567 gen_update_nip(ctx, ctx->nip - 4);
4568 gen_addr_imm_index(ctx, 0);
4569 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
4570 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4571 op_POWER2_stfq();
4572 if (ra != 0)
4573 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4574}
4575
4576/* stfqux */
4577GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
4578{
4579 int ra = rA(ctx->opcode);
4580
4581 /* NIP cannot be restored if the memory exception comes from an helper */
4582 gen_update_nip(ctx, ctx->nip - 4);
4583 gen_addr_reg_index(ctx);
4584 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
4585 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4586 op_POWER2_stfq();
4587 if (ra != 0)
4588 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4589}
4590
4591/* stfqx */
4592GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
4593{
4594 /* NIP cannot be restored if the memory exception comes from an helper */
4595 gen_update_nip(ctx, ctx->nip - 4);
4596 gen_addr_reg_index(ctx);
4597 tcg_gen_mov_i64(cpu_FT[0], cpu_fpr[rS(ctx->opcode)]);
4598 tcg_gen_mov_i64(cpu_FT[1], cpu_fpr[rS(ctx->opcode) + 1]);
4599 op_POWER2_stfq();
4600}
4601
4602/* BookE specific instructions */
4603/* XXX: not implemented on 440 ? */
4604GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
4605{
4606 /* XXX: TODO */
4607 GEN_EXCP_INVAL(ctx);
4608}
4609
4610/* XXX: not implemented on 440 ? */
4611GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
4612{
4613#if defined(CONFIG_USER_ONLY)
4614 GEN_EXCP_PRIVOPC(ctx);
4615#else
4616 if (unlikely(!ctx->supervisor)) {
4617 GEN_EXCP_PRIVOPC(ctx);
4618 return;
4619 }
4620 gen_addr_reg_index(ctx);
4621 /* Use the same micro-ops as for tlbie */
4622#if defined(TARGET_PPC64)
4623 if (ctx->sf_mode)
4624 gen_op_tlbie_64();
4625 else
4626#endif
4627 gen_op_tlbie();
4628#endif
4629}
4630
4631/* All 405 MAC instructions are translated here */
4632static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
4633 int opc2, int opc3,
4634 int ra, int rb, int rt, int Rc)
4635{
4636 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[ra]);
4637 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
4638 switch (opc3 & 0x0D) {
4639 case 0x05:
4640 /* macchw - macchw. - macchwo - macchwo. */
4641 /* macchws - macchws. - macchwso - macchwso. */
4642 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
4643 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
4644 /* mulchw - mulchw. */
4645 gen_op_405_mulchw();
4646 break;
4647 case 0x04:
4648 /* macchwu - macchwu. - macchwuo - macchwuo. */
4649 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
4650 /* mulchwu - mulchwu. */
4651 gen_op_405_mulchwu();
4652 break;
4653 case 0x01:
4654 /* machhw - machhw. - machhwo - machhwo. */
4655 /* machhws - machhws. - machhwso - machhwso. */
4656 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
4657 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
4658 /* mulhhw - mulhhw. */
4659 gen_op_405_mulhhw();
4660 break;
4661 case 0x00:
4662 /* machhwu - machhwu. - machhwuo - machhwuo. */
4663 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
4664 /* mulhhwu - mulhhwu. */
4665 gen_op_405_mulhhwu();
4666 break;
4667 case 0x0D:
4668 /* maclhw - maclhw. - maclhwo - maclhwo. */
4669 /* maclhws - maclhws. - maclhwso - maclhwso. */
4670 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
4671 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
4672 /* mullhw - mullhw. */
4673 gen_op_405_mullhw();
4674 break;
4675 case 0x0C:
4676 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
4677 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
4678 /* mullhwu - mullhwu. */
4679 gen_op_405_mullhwu();
4680 break;
4681 }
4682 if (opc2 & 0x02) {
4683 /* nmultiply-and-accumulate (0x0E) */
4684 gen_op_neg();
4685 }
4686 if (opc2 & 0x04) {
4687 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
4688 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rt]);
4689 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
4690 gen_op_405_add_T0_T2();
4691 }
4692 if (opc3 & 0x10) {
4693 /* Check overflow */
4694 if (opc3 & 0x01)
4695 gen_op_check_addo();
4696 else
4697 gen_op_405_check_ovu();
4698 }
4699 if (opc3 & 0x02) {
4700 /* Saturate */
4701 if (opc3 & 0x01)
4702 gen_op_405_check_sat();
4703 else
4704 gen_op_405_check_satu();
4705 }
4706 tcg_gen_mov_tl(cpu_gpr[rt], cpu_T[0]);
4707 if (unlikely(Rc) != 0) {
4708 /* Update Rc0 */
4709 gen_set_Rc0(ctx);
4710 }
4711}
4712
4713#define GEN_MAC_HANDLER(name, opc2, opc3) \
4714GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
4715{ \
4716 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
4717 rD(ctx->opcode), Rc(ctx->opcode)); \
4718}
4719
4720/* macchw - macchw. */
4721GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
4722/* macchwo - macchwo. */
4723GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
4724/* macchws - macchws. */
4725GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
4726/* macchwso - macchwso. */
4727GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
4728/* macchwsu - macchwsu. */
4729GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
4730/* macchwsuo - macchwsuo. */
4731GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
4732/* macchwu - macchwu. */
4733GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
4734/* macchwuo - macchwuo. */
4735GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
4736/* machhw - machhw. */
4737GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
4738/* machhwo - machhwo. */
4739GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
4740/* machhws - machhws. */
4741GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
4742/* machhwso - machhwso. */
4743GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
4744/* machhwsu - machhwsu. */
4745GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
4746/* machhwsuo - machhwsuo. */
4747GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
4748/* machhwu - machhwu. */
4749GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
4750/* machhwuo - machhwuo. */
4751GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
4752/* maclhw - maclhw. */
4753GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
4754/* maclhwo - maclhwo. */
4755GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
4756/* maclhws - maclhws. */
4757GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
4758/* maclhwso - maclhwso. */
4759GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
4760/* maclhwu - maclhwu. */
4761GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
4762/* maclhwuo - maclhwuo. */
4763GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
4764/* maclhwsu - maclhwsu. */
4765GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
4766/* maclhwsuo - maclhwsuo. */
4767GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
4768/* nmacchw - nmacchw. */
4769GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
4770/* nmacchwo - nmacchwo. */
4771GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
4772/* nmacchws - nmacchws. */
4773GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
4774/* nmacchwso - nmacchwso. */
4775GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
4776/* nmachhw - nmachhw. */
4777GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
4778/* nmachhwo - nmachhwo. */
4779GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
4780/* nmachhws - nmachhws. */
4781GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
4782/* nmachhwso - nmachhwso. */
4783GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
4784/* nmaclhw - nmaclhw. */
4785GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
4786/* nmaclhwo - nmaclhwo. */
4787GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
4788/* nmaclhws - nmaclhws. */
4789GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
4790/* nmaclhwso - nmaclhwso. */
4791GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
4792
4793/* mulchw - mulchw. */
4794GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
4795/* mulchwu - mulchwu. */
4796GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
4797/* mulhhw - mulhhw. */
4798GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
4799/* mulhhwu - mulhhwu. */
4800GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
4801/* mullhw - mullhw. */
4802GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
4803/* mullhwu - mullhwu. */
4804GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
4805
4806/* mfdcr */
4807GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
4808{
4809#if defined(CONFIG_USER_ONLY)
4810 GEN_EXCP_PRIVREG(ctx);
4811#else
4812 uint32_t dcrn = SPR(ctx->opcode);
4813
4814 if (unlikely(!ctx->supervisor)) {
4815 GEN_EXCP_PRIVREG(ctx);
4816 return;
4817 }
4818 tcg_gen_movi_tl(cpu_T[0], dcrn);
4819 gen_op_load_dcr();
4820 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4821#endif
4822}
4823
4824/* mtdcr */
4825GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
4826{
4827#if defined(CONFIG_USER_ONLY)
4828 GEN_EXCP_PRIVREG(ctx);
4829#else
4830 uint32_t dcrn = SPR(ctx->opcode);
4831
4832 if (unlikely(!ctx->supervisor)) {
4833 GEN_EXCP_PRIVREG(ctx);
4834 return;
4835 }
4836 tcg_gen_movi_tl(cpu_T[0], dcrn);
4837 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4838 gen_op_store_dcr();
4839#endif
4840}
4841
4842/* mfdcrx */
4843/* XXX: not implemented on 440 ? */
4844GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
4845{
4846#if defined(CONFIG_USER_ONLY)
4847 GEN_EXCP_PRIVREG(ctx);
4848#else
4849 if (unlikely(!ctx->supervisor)) {
4850 GEN_EXCP_PRIVREG(ctx);
4851 return;
4852 }
4853 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4854 gen_op_load_dcr();
4855 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4856 /* Note: Rc update flag set leads to undefined state of Rc0 */
4857#endif
4858}
4859
4860/* mtdcrx */
4861/* XXX: not implemented on 440 ? */
4862GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
4863{
4864#if defined(CONFIG_USER_ONLY)
4865 GEN_EXCP_PRIVREG(ctx);
4866#else
4867 if (unlikely(!ctx->supervisor)) {
4868 GEN_EXCP_PRIVREG(ctx);
4869 return;
4870 }
4871 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4872 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4873 gen_op_store_dcr();
4874 /* Note: Rc update flag set leads to undefined state of Rc0 */
4875#endif
4876}
4877
4878/* mfdcrux (PPC 460) : user-mode access to DCR */
4879GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
4880{
4881 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4882 gen_op_load_dcr();
4883 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4884 /* Note: Rc update flag set leads to undefined state of Rc0 */
4885}
4886
4887/* mtdcrux (PPC 460) : user-mode access to DCR */
4888GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
4889{
4890 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4891 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4892 gen_op_store_dcr();
4893 /* Note: Rc update flag set leads to undefined state of Rc0 */
4894}
4895
4896/* dccci */
4897GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
4898{
4899#if defined(CONFIG_USER_ONLY)
4900 GEN_EXCP_PRIVOPC(ctx);
4901#else
4902 if (unlikely(!ctx->supervisor)) {
4903 GEN_EXCP_PRIVOPC(ctx);
4904 return;
4905 }
4906 /* interpreted as no-op */
4907#endif
4908}
4909
4910/* dcread */
4911GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
4912{
4913#if defined(CONFIG_USER_ONLY)
4914 GEN_EXCP_PRIVOPC(ctx);
4915#else
4916 if (unlikely(!ctx->supervisor)) {
4917 GEN_EXCP_PRIVOPC(ctx);
4918 return;
4919 }
4920 gen_addr_reg_index(ctx);
4921 op_ldst(lwz);
4922 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4923#endif
4924}
4925
4926/* icbt */
4927GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
4928{
4929 /* interpreted as no-op */
4930 /* XXX: specification say this is treated as a load by the MMU
4931 * but does not generate any exception
4932 */
4933}
4934
4935/* iccci */
4936GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
4937{
4938#if defined(CONFIG_USER_ONLY)
4939 GEN_EXCP_PRIVOPC(ctx);
4940#else
4941 if (unlikely(!ctx->supervisor)) {
4942 GEN_EXCP_PRIVOPC(ctx);
4943 return;
4944 }
4945 /* interpreted as no-op */
4946#endif
4947}
4948
4949/* icread */
4950GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
4951{
4952#if defined(CONFIG_USER_ONLY)
4953 GEN_EXCP_PRIVOPC(ctx);
4954#else
4955 if (unlikely(!ctx->supervisor)) {
4956 GEN_EXCP_PRIVOPC(ctx);
4957 return;
4958 }
4959 /* interpreted as no-op */
4960#endif
4961}
4962
4963/* rfci (supervisor only) */
4964GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
4965{
4966#if defined(CONFIG_USER_ONLY)
4967 GEN_EXCP_PRIVOPC(ctx);
4968#else
4969 if (unlikely(!ctx->supervisor)) {
4970 GEN_EXCP_PRIVOPC(ctx);
4971 return;
4972 }
4973 /* Restore CPU state */
4974 gen_op_40x_rfci();
4975 GEN_SYNC(ctx);
4976#endif
4977}
4978
4979GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
4980{
4981#if defined(CONFIG_USER_ONLY)
4982 GEN_EXCP_PRIVOPC(ctx);
4983#else
4984 if (unlikely(!ctx->supervisor)) {
4985 GEN_EXCP_PRIVOPC(ctx);
4986 return;
4987 }
4988 /* Restore CPU state */
4989 gen_op_rfci();
4990 GEN_SYNC(ctx);
4991#endif
4992}
4993
4994/* BookE specific */
4995/* XXX: not implemented on 440 ? */
4996GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
4997{
4998#if defined(CONFIG_USER_ONLY)
4999 GEN_EXCP_PRIVOPC(ctx);
5000#else
5001 if (unlikely(!ctx->supervisor)) {
5002 GEN_EXCP_PRIVOPC(ctx);
5003 return;
5004 }
5005 /* Restore CPU state */
5006 gen_op_rfdi();
5007 GEN_SYNC(ctx);
5008#endif
5009}
5010
5011/* XXX: not implemented on 440 ? */
5012GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5013{
5014#if defined(CONFIG_USER_ONLY)
5015 GEN_EXCP_PRIVOPC(ctx);
5016#else
5017 if (unlikely(!ctx->supervisor)) {
5018 GEN_EXCP_PRIVOPC(ctx);
5019 return;
5020 }
5021 /* Restore CPU state */
5022 gen_op_rfmci();
5023 GEN_SYNC(ctx);
5024#endif
5025}
5026
5027/* TLB management - PowerPC 405 implementation */
5028/* tlbre */
5029GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5030{
5031#if defined(CONFIG_USER_ONLY)
5032 GEN_EXCP_PRIVOPC(ctx);
5033#else
5034 if (unlikely(!ctx->supervisor)) {
5035 GEN_EXCP_PRIVOPC(ctx);
5036 return;
5037 }
5038 switch (rB(ctx->opcode)) {
5039 case 0:
5040 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5041 gen_op_4xx_tlbre_hi();
5042 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5043 break;
5044 case 1:
5045 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5046 gen_op_4xx_tlbre_lo();
5047 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5048 break;
5049 default:
5050 GEN_EXCP_INVAL(ctx);
5051 break;
5052 }
5053#endif
5054}
5055
5056/* tlbsx - tlbsx. */
5057GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5058{
5059#if defined(CONFIG_USER_ONLY)
5060 GEN_EXCP_PRIVOPC(ctx);
5061#else
5062 if (unlikely(!ctx->supervisor)) {
5063 GEN_EXCP_PRIVOPC(ctx);
5064 return;
5065 }
5066 gen_addr_reg_index(ctx);
5067 gen_op_4xx_tlbsx();
5068 if (Rc(ctx->opcode))
5069 gen_op_4xx_tlbsx_check();
5070 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5071#endif
5072}
5073
5074/* tlbwe */
5075GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
5076{
5077#if defined(CONFIG_USER_ONLY)
5078 GEN_EXCP_PRIVOPC(ctx);
5079#else
5080 if (unlikely(!ctx->supervisor)) {
5081 GEN_EXCP_PRIVOPC(ctx);
5082 return;
5083 }
5084 switch (rB(ctx->opcode)) {
5085 case 0:
5086 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5087 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5088 gen_op_4xx_tlbwe_hi();
5089 break;
5090 case 1:
5091 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5092 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5093 gen_op_4xx_tlbwe_lo();
5094 break;
5095 default:
5096 GEN_EXCP_INVAL(ctx);
5097 break;
5098 }
5099#endif
5100}
5101
5102/* TLB management - PowerPC 440 implementation */
5103/* tlbre */
5104GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5105{
5106#if defined(CONFIG_USER_ONLY)
5107 GEN_EXCP_PRIVOPC(ctx);
5108#else
5109 if (unlikely(!ctx->supervisor)) {
5110 GEN_EXCP_PRIVOPC(ctx);
5111 return;
5112 }
5113 switch (rB(ctx->opcode)) {
5114 case 0:
5115 case 1:
5116 case 2:
5117 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5118 gen_op_440_tlbre(rB(ctx->opcode));
5119 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5120 break;
5121 default:
5122 GEN_EXCP_INVAL(ctx);
5123 break;
5124 }
5125#endif
5126}
5127
5128/* tlbsx - tlbsx. */
5129GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5130{
5131#if defined(CONFIG_USER_ONLY)
5132 GEN_EXCP_PRIVOPC(ctx);
5133#else
5134 if (unlikely(!ctx->supervisor)) {
5135 GEN_EXCP_PRIVOPC(ctx);
5136 return;
5137 }
5138 gen_addr_reg_index(ctx);
5139 gen_op_440_tlbsx();
5140 if (Rc(ctx->opcode))
5141 gen_op_4xx_tlbsx_check();
5142 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5143#endif
5144}
5145
5146/* tlbwe */
5147GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5148{
5149#if defined(CONFIG_USER_ONLY)
5150 GEN_EXCP_PRIVOPC(ctx);
5151#else
5152 if (unlikely(!ctx->supervisor)) {
5153 GEN_EXCP_PRIVOPC(ctx);
5154 return;
5155 }
5156 switch (rB(ctx->opcode)) {
5157 case 0:
5158 case 1:
5159 case 2:
5160 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5161 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5162 gen_op_440_tlbwe(rB(ctx->opcode));
5163 break;
5164 default:
5165 GEN_EXCP_INVAL(ctx);
5166 break;
5167 }
5168#endif
5169}
5170
5171/* wrtee */
5172GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5173{
5174#if defined(CONFIG_USER_ONLY)
5175 GEN_EXCP_PRIVOPC(ctx);
5176#else
5177 if (unlikely(!ctx->supervisor)) {
5178 GEN_EXCP_PRIVOPC(ctx);
5179 return;
5180 }
5181 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
5182 gen_op_wrte();
5183 /* Stop translation to have a chance to raise an exception
5184 * if we just set msr_ee to 1
5185 */
5186 GEN_STOP(ctx);
5187#endif
5188}
5189
5190/* wrteei */
5191GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5192{
5193#if defined(CONFIG_USER_ONLY)
5194 GEN_EXCP_PRIVOPC(ctx);
5195#else
5196 if (unlikely(!ctx->supervisor)) {
5197 GEN_EXCP_PRIVOPC(ctx);
5198 return;
5199 }
5200 tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
5201 gen_op_wrte();
5202 /* Stop translation to have a chance to raise an exception
5203 * if we just set msr_ee to 1
5204 */
5205 GEN_STOP(ctx);
5206#endif
5207}
5208
5209/* PowerPC 440 specific instructions */
5210/* dlmzb */
5211GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5212{
5213 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
5214 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5215 gen_op_440_dlmzb();
5216 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
5217 gen_op_store_xer_bc();
5218 if (Rc(ctx->opcode)) {
5219 gen_op_440_dlmzb_update_Rc();
5220 tcg_gen_andi_i32(cpu_crf[0], cpu_T[0], 0xf);
5221 }
5222}
5223
5224/* mbar replaces eieio on 440 */
5225GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5226{
5227 /* interpreted as no-op */
5228}
5229
5230/* msync replaces sync on 440 */
5231GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5232{
5233 /* interpreted as no-op */
5234}
5235
5236/* icbt */
5237GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5238{
5239 /* interpreted as no-op */
5240 /* XXX: specification say this is treated as a load by the MMU
5241 * but does not generate any exception
5242 */
5243}
5244
5245/*** Altivec vector extension ***/
5246/* Altivec registers moves */
5247
5248static always_inline void gen_load_avr(int t, int reg) {
5249 tcg_gen_mov_i64(cpu_AVRh[t], cpu_avrh[reg]);
5250 tcg_gen_mov_i64(cpu_AVRl[t], cpu_avrl[reg]);
5251}
5252
5253static always_inline void gen_store_avr(int reg, int t) {
5254 tcg_gen_mov_i64(cpu_avrh[reg], cpu_AVRh[t]);
5255 tcg_gen_mov_i64(cpu_avrl[reg], cpu_AVRl[t]);
5256}
5257
5258#define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5259#define OP_VR_LD_TABLE(name) \
5260static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = { \
5261 GEN_MEM_FUNCS(vr_l##name), \
5262};
5263#define OP_VR_ST_TABLE(name) \
5264static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = { \
5265 GEN_MEM_FUNCS(vr_st##name), \
5266};
5267
5268#define GEN_VR_LDX(name, opc2, opc3) \
5269GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5270{ \
5271 if (unlikely(!ctx->altivec_enabled)) { \
5272 GEN_EXCP_NO_VR(ctx); \
5273 return; \
5274 } \
5275 gen_addr_reg_index(ctx); \
5276 op_vr_ldst(vr_l##name); \
5277 gen_store_avr(rD(ctx->opcode), 0); \
5278}
5279
5280#define GEN_VR_STX(name, opc2, opc3) \
5281GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5282{ \
5283 if (unlikely(!ctx->altivec_enabled)) { \
5284 GEN_EXCP_NO_VR(ctx); \
5285 return; \
5286 } \
5287 gen_addr_reg_index(ctx); \
5288 gen_load_avr(0, rS(ctx->opcode)); \
5289 op_vr_ldst(vr_st##name); \
5290}
5291
5292OP_VR_LD_TABLE(vx);
5293GEN_VR_LDX(vx, 0x07, 0x03);
5294/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
5295#define gen_op_vr_lvxl gen_op_vr_lvx
5296GEN_VR_LDX(vxl, 0x07, 0x0B);
5297
5298OP_VR_ST_TABLE(vx);
5299GEN_VR_STX(vx, 0x07, 0x07);
5300/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
5301#define gen_op_vr_stvxl gen_op_vr_stvx
5302GEN_VR_STX(vxl, 0x07, 0x0F);
5303
5304/*** SPE extension ***/
5305/* Register moves */
5306
5307static always_inline void gen_load_gpr64(TCGv t, int reg) {
5308#if defined(TARGET_PPC64)
5309 tcg_gen_mov_i64(t, cpu_gpr[reg]);
5310#else
5311 tcg_gen_extu_i32_i64(t, cpu_gprh[reg]);
5312 tcg_gen_shli_i64(t, t, 32);
5313 TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
5314 tcg_gen_extu_i32_i64(tmp, cpu_gpr[reg]);
5315 tcg_gen_or_i64(t, t, tmp);
5316 tcg_temp_free(tmp);
5317#endif
5318}
5319
5320static always_inline void gen_store_gpr64(int reg, TCGv t) {
5321#if defined(TARGET_PPC64)
5322 tcg_gen_mov_i64(cpu_gpr[reg], t);
5323#else
5324 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
5325 TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
5326 tcg_gen_shri_i64(tmp, t, 32);
5327 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
5328 tcg_temp_free(tmp);
5329#endif
5330}
5331
5332#define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5333GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5334{ \
5335 if (Rc(ctx->opcode)) \
5336 gen_##name1(ctx); \
5337 else \
5338 gen_##name0(ctx); \
5339}
5340
5341/* Handler for undefined SPE opcodes */
5342static always_inline void gen_speundef (DisasContext *ctx)
5343{
5344 GEN_EXCP_INVAL(ctx);
5345}
5346
5347/* SPE load and stores */
5348static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
5349{
5350 target_long simm = rB(ctx->opcode);
5351
5352 if (rA(ctx->opcode) == 0) {
5353 tcg_gen_movi_tl(cpu_T[0], simm << sh);
5354 } else {
5355 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5356 if (likely(simm != 0))
5357 tcg_gen_addi_tl(cpu_T[0], cpu_T[0], simm << sh);
5358 }
5359}
5360
5361#define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5362#define OP_SPE_LD_TABLE(name) \
5363static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = { \
5364 GEN_MEM_FUNCS(spe_l##name), \
5365};
5366#define OP_SPE_ST_TABLE(name) \
5367static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = { \
5368 GEN_MEM_FUNCS(spe_st##name), \
5369};
5370
5371#define GEN_SPE_LD(name, sh) \
5372static always_inline void gen_evl##name (DisasContext *ctx) \
5373{ \
5374 if (unlikely(!ctx->spe_enabled)) { \
5375 GEN_EXCP_NO_AP(ctx); \
5376 return; \
5377 } \
5378 gen_addr_spe_imm_index(ctx, sh); \
5379 op_spe_ldst(spe_l##name); \
5380 gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
5381}
5382
5383#define GEN_SPE_LDX(name) \
5384static always_inline void gen_evl##name##x (DisasContext *ctx) \
5385{ \
5386 if (unlikely(!ctx->spe_enabled)) { \
5387 GEN_EXCP_NO_AP(ctx); \
5388 return; \
5389 } \
5390 gen_addr_reg_index(ctx); \
5391 op_spe_ldst(spe_l##name); \
5392 gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
5393}
5394
5395#define GEN_SPEOP_LD(name, sh) \
5396OP_SPE_LD_TABLE(name); \
5397GEN_SPE_LD(name, sh); \
5398GEN_SPE_LDX(name)
5399
5400#define GEN_SPE_ST(name, sh) \
5401static always_inline void gen_evst##name (DisasContext *ctx) \
5402{ \
5403 if (unlikely(!ctx->spe_enabled)) { \
5404 GEN_EXCP_NO_AP(ctx); \
5405 return; \
5406 } \
5407 gen_addr_spe_imm_index(ctx, sh); \
5408 gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
5409 op_spe_ldst(spe_st##name); \
5410}
5411
5412#define GEN_SPE_STX(name) \
5413static always_inline void gen_evst##name##x (DisasContext *ctx) \
5414{ \
5415 if (unlikely(!ctx->spe_enabled)) { \
5416 GEN_EXCP_NO_AP(ctx); \
5417 return; \
5418 } \
5419 gen_addr_reg_index(ctx); \
5420 gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
5421 op_spe_ldst(spe_st##name); \
5422}
5423
5424#define GEN_SPEOP_ST(name, sh) \
5425OP_SPE_ST_TABLE(name); \
5426GEN_SPE_ST(name, sh); \
5427GEN_SPE_STX(name)
5428
5429#define GEN_SPEOP_LDST(name, sh) \
5430GEN_SPEOP_LD(name, sh); \
5431GEN_SPEOP_ST(name, sh)
5432
5433/* SPE arithmetic and logic */
5434#define GEN_SPEOP_ARITH2(name) \
5435static always_inline void gen_##name (DisasContext *ctx) \
5436{ \
5437 if (unlikely(!ctx->spe_enabled)) { \
5438 GEN_EXCP_NO_AP(ctx); \
5439 return; \
5440 } \
5441 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5442 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
5443 gen_op_##name(); \
5444 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5445}
5446
5447#define GEN_SPEOP_ARITH1(name) \
5448static always_inline void gen_##name (DisasContext *ctx) \
5449{ \
5450 if (unlikely(!ctx->spe_enabled)) { \
5451 GEN_EXCP_NO_AP(ctx); \
5452 return; \
5453 } \
5454 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5455 gen_op_##name(); \
5456 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5457}
5458
5459#define GEN_SPEOP_COMP(name) \
5460static always_inline void gen_##name (DisasContext *ctx) \
5461{ \
5462 if (unlikely(!ctx->spe_enabled)) { \
5463 GEN_EXCP_NO_AP(ctx); \
5464 return; \
5465 } \
5466 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5467 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
5468 gen_op_##name(); \
5469 tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_T[0], 0xf); \
5470}
5471
5472/* Logical */
5473GEN_SPEOP_ARITH2(evand);
5474GEN_SPEOP_ARITH2(evandc);
5475GEN_SPEOP_ARITH2(evxor);
5476GEN_SPEOP_ARITH2(evor);
5477GEN_SPEOP_ARITH2(evnor);
5478GEN_SPEOP_ARITH2(eveqv);
5479GEN_SPEOP_ARITH2(evorc);
5480GEN_SPEOP_ARITH2(evnand);
5481GEN_SPEOP_ARITH2(evsrwu);
5482GEN_SPEOP_ARITH2(evsrws);
5483GEN_SPEOP_ARITH2(evslw);
5484GEN_SPEOP_ARITH2(evrlw);
5485GEN_SPEOP_ARITH2(evmergehi);
5486GEN_SPEOP_ARITH2(evmergelo);
5487GEN_SPEOP_ARITH2(evmergehilo);
5488GEN_SPEOP_ARITH2(evmergelohi);
5489
5490/* Arithmetic */
5491GEN_SPEOP_ARITH2(evaddw);
5492GEN_SPEOP_ARITH2(evsubfw);
5493GEN_SPEOP_ARITH1(evabs);
5494GEN_SPEOP_ARITH1(evneg);
5495GEN_SPEOP_ARITH1(evextsb);
5496GEN_SPEOP_ARITH1(evextsh);
5497GEN_SPEOP_ARITH1(evrndw);
5498GEN_SPEOP_ARITH1(evcntlzw);
5499GEN_SPEOP_ARITH1(evcntlsw);
5500static always_inline void gen_brinc (DisasContext *ctx)
5501{
5502 /* Note: brinc is usable even if SPE is disabled */
5503 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5504 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5505 gen_op_brinc();
5506 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5507}
5508
5509#define GEN_SPEOP_ARITH_IMM2(name) \
5510static always_inline void gen_##name##i (DisasContext *ctx) \
5511{ \
5512 if (unlikely(!ctx->spe_enabled)) { \
5513 GEN_EXCP_NO_AP(ctx); \
5514 return; \
5515 } \
5516 gen_load_gpr64(cpu_T64[0], rB(ctx->opcode)); \
5517 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
5518 gen_op_##name(); \
5519 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5520}
5521
5522#define GEN_SPEOP_LOGIC_IMM2(name) \
5523static always_inline void gen_##name##i (DisasContext *ctx) \
5524{ \
5525 if (unlikely(!ctx->spe_enabled)) { \
5526 GEN_EXCP_NO_AP(ctx); \
5527 return; \
5528 } \
5529 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5530 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
5531 gen_op_##name(); \
5532 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5533}
5534
5535GEN_SPEOP_ARITH_IMM2(evaddw);
5536#define gen_evaddiw gen_evaddwi
5537GEN_SPEOP_ARITH_IMM2(evsubfw);
5538#define gen_evsubifw gen_evsubfwi
5539GEN_SPEOP_LOGIC_IMM2(evslw);
5540GEN_SPEOP_LOGIC_IMM2(evsrwu);
5541#define gen_evsrwis gen_evsrwsi
5542GEN_SPEOP_LOGIC_IMM2(evsrws);
5543#define gen_evsrwiu gen_evsrwui
5544GEN_SPEOP_LOGIC_IMM2(evrlw);
5545
5546static always_inline void gen_evsplati (DisasContext *ctx)
5547{
5548 int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
5549
5550 gen_op_splatwi_T0_64(imm);
5551 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5552}
5553
5554static always_inline void gen_evsplatfi (DisasContext *ctx)
5555{
5556 uint32_t imm = rA(ctx->opcode) << 27;
5557
5558 gen_op_splatwi_T0_64(imm);
5559 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5560}
5561
5562/* Comparison */
5563GEN_SPEOP_COMP(evcmpgtu);
5564GEN_SPEOP_COMP(evcmpgts);
5565GEN_SPEOP_COMP(evcmpltu);
5566GEN_SPEOP_COMP(evcmplts);
5567GEN_SPEOP_COMP(evcmpeq);
5568
5569GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
5570GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
5571GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
5572GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
5573GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
5574GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
5575GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
5576GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
5577GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
5578GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
5579GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
5580GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
5581GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
5582GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
5583GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
5584GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
5585GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
5586GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
5587GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
5588GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
5589GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
5590GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
5591GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
5592GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
5593GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
5594
5595static always_inline void gen_evsel (DisasContext *ctx)
5596{
5597 if (unlikely(!ctx->spe_enabled)) {
5598 GEN_EXCP_NO_AP(ctx);
5599 return;
5600 }
5601 tcg_gen_mov_i32(cpu_T[0], cpu_crf[ctx->opcode & 0x7]);
5602 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
5603 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
5604 gen_op_evsel();
5605 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5606}
5607
5608GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
5609{
5610 gen_evsel(ctx);
5611}
5612GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
5613{
5614 gen_evsel(ctx);
5615}
5616GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
5617{
5618 gen_evsel(ctx);
5619}
5620GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
5621{
5622 gen_evsel(ctx);
5623}
5624
5625/* Load and stores */
5626#if defined(TARGET_PPC64)
5627/* In that case, we already have 64 bits load & stores
5628 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
5629 */
5630#define gen_op_spe_ldd_raw gen_op_ld_raw
5631#define gen_op_spe_ldd_user gen_op_ld_user
5632#define gen_op_spe_ldd_kernel gen_op_ld_kernel
5633#define gen_op_spe_ldd_hypv gen_op_ld_hypv
5634#define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
5635#define gen_op_spe_ldd_64_user gen_op_ld_64_user
5636#define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
5637#define gen_op_spe_ldd_64_hypv gen_op_ld_64_hypv
5638#define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
5639#define gen_op_spe_ldd_le_user gen_op_ld_le_user
5640#define gen_op_spe_ldd_le_kernel gen_op_ld_le_kernel
5641#define gen_op_spe_ldd_le_hypv gen_op_ld_le_hypv
5642#define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
5643#define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
5644#define gen_op_spe_ldd_le_64_kernel gen_op_ld_le_64_kernel
5645#define gen_op_spe_ldd_le_64_hypv gen_op_ld_le_64_hypv
5646#define gen_op_spe_stdd_raw gen_op_std_raw
5647#define gen_op_spe_stdd_user gen_op_std_user
5648#define gen_op_spe_stdd_kernel gen_op_std_kernel
5649#define gen_op_spe_stdd_hypv gen_op_std_hypv
5650#define gen_op_spe_stdd_64_raw gen_op_std_64_raw
5651#define gen_op_spe_stdd_64_user gen_op_std_64_user
5652#define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
5653#define gen_op_spe_stdd_64_hypv gen_op_std_64_hypv
5654#define gen_op_spe_stdd_le_raw gen_op_std_le_raw
5655#define gen_op_spe_stdd_le_user gen_op_std_le_user
5656#define gen_op_spe_stdd_le_kernel gen_op_std_le_kernel
5657#define gen_op_spe_stdd_le_hypv gen_op_std_le_hypv
5658#define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
5659#define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
5660#define gen_op_spe_stdd_le_64_kernel gen_op_std_le_64_kernel
5661#define gen_op_spe_stdd_le_64_hypv gen_op_std_le_64_hypv
5662#endif /* defined(TARGET_PPC64) */
5663GEN_SPEOP_LDST(dd, 3);
5664GEN_SPEOP_LDST(dw, 3);
5665GEN_SPEOP_LDST(dh, 3);
5666GEN_SPEOP_LDST(whe, 2);
5667GEN_SPEOP_LD(whou, 2);
5668GEN_SPEOP_LD(whos, 2);
5669GEN_SPEOP_ST(who, 2);
5670
5671#if defined(TARGET_PPC64)
5672/* In that case, spe_stwwo is equivalent to stw */
5673#define gen_op_spe_stwwo_raw gen_op_stw_raw
5674#define gen_op_spe_stwwo_user gen_op_stw_user
5675#define gen_op_spe_stwwo_kernel gen_op_stw_kernel
5676#define gen_op_spe_stwwo_hypv gen_op_stw_hypv
5677#define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
5678#define gen_op_spe_stwwo_le_user gen_op_stw_le_user
5679#define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
5680#define gen_op_spe_stwwo_le_hypv gen_op_stw_le_hypv
5681#define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
5682#define gen_op_spe_stwwo_64_user gen_op_stw_64_user
5683#define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
5684#define gen_op_spe_stwwo_64_hypv gen_op_stw_64_hypv
5685#define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
5686#define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
5687#define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5688#define gen_op_spe_stwwo_le_64_hypv gen_op_stw_le_64_hypv
5689#endif
5690#define _GEN_OP_SPE_STWWE(suffix) \
5691static always_inline void gen_op_spe_stwwe_##suffix (void) \
5692{ \
5693 gen_op_srli32_T1_64(); \
5694 gen_op_spe_stwwo_##suffix(); \
5695}
5696#define _GEN_OP_SPE_STWWE_LE(suffix) \
5697static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
5698{ \
5699 gen_op_srli32_T1_64(); \
5700 gen_op_spe_stwwo_le_##suffix(); \
5701}
5702#if defined(TARGET_PPC64)
5703#define GEN_OP_SPE_STWWE(suffix) \
5704_GEN_OP_SPE_STWWE(suffix); \
5705_GEN_OP_SPE_STWWE_LE(suffix); \
5706static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
5707{ \
5708 gen_op_srli32_T1_64(); \
5709 gen_op_spe_stwwo_64_##suffix(); \
5710} \
5711static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
5712{ \
5713 gen_op_srli32_T1_64(); \
5714 gen_op_spe_stwwo_le_64_##suffix(); \
5715}
5716#else
5717#define GEN_OP_SPE_STWWE(suffix) \
5718_GEN_OP_SPE_STWWE(suffix); \
5719_GEN_OP_SPE_STWWE_LE(suffix)
5720#endif
5721#if defined(CONFIG_USER_ONLY)
5722GEN_OP_SPE_STWWE(raw);
5723#else /* defined(CONFIG_USER_ONLY) */
5724GEN_OP_SPE_STWWE(user);
5725GEN_OP_SPE_STWWE(kernel);
5726GEN_OP_SPE_STWWE(hypv);
5727#endif /* defined(CONFIG_USER_ONLY) */
5728GEN_SPEOP_ST(wwe, 2);
5729GEN_SPEOP_ST(wwo, 2);
5730
5731#define GEN_SPE_LDSPLAT(name, op, suffix) \
5732static always_inline void gen_op_spe_l##name##_##suffix (void) \
5733{ \
5734 gen_op_##op##_##suffix(); \
5735 gen_op_splatw_T1_64(); \
5736}
5737
5738#define GEN_OP_SPE_LHE(suffix) \
5739static always_inline void gen_op_spe_lhe_##suffix (void) \
5740{ \
5741 gen_op_spe_lh_##suffix(); \
5742 gen_op_sli16_T1_64(); \
5743}
5744
5745#define GEN_OP_SPE_LHX(suffix) \
5746static always_inline void gen_op_spe_lhx_##suffix (void) \
5747{ \
5748 gen_op_spe_lh_##suffix(); \
5749 gen_op_extsh_T1_64(); \
5750}
5751
5752#if defined(CONFIG_USER_ONLY)
5753GEN_OP_SPE_LHE(raw);
5754GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
5755GEN_OP_SPE_LHE(le_raw);
5756GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
5757GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
5758GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
5759GEN_OP_SPE_LHX(raw);
5760GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
5761GEN_OP_SPE_LHX(le_raw);
5762GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
5763#if defined(TARGET_PPC64)
5764GEN_OP_SPE_LHE(64_raw);
5765GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
5766GEN_OP_SPE_LHE(le_64_raw);
5767GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
5768GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
5769GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
5770GEN_OP_SPE_LHX(64_raw);
5771GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
5772GEN_OP_SPE_LHX(le_64_raw);
5773GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
5774#endif
5775#else
5776GEN_OP_SPE_LHE(user);
5777GEN_OP_SPE_LHE(kernel);
5778GEN_OP_SPE_LHE(hypv);
5779GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
5780GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
5781GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
5782GEN_OP_SPE_LHE(le_user);
5783GEN_OP_SPE_LHE(le_kernel);
5784GEN_OP_SPE_LHE(le_hypv);
5785GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
5786GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
5787GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
5788GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
5789GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
5790GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
5791GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
5792GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
5793GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
5794GEN_OP_SPE_LHX(user);
5795GEN_OP_SPE_LHX(kernel);
5796GEN_OP_SPE_LHX(hypv);
5797GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
5798GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
5799GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
5800GEN_OP_SPE_LHX(le_user);
5801GEN_OP_SPE_LHX(le_kernel);
5802GEN_OP_SPE_LHX(le_hypv);
5803GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
5804GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
5805GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
5806#if defined(TARGET_PPC64)
5807GEN_OP_SPE_LHE(64_user);
5808GEN_OP_SPE_LHE(64_kernel);
5809GEN_OP_SPE_LHE(64_hypv);
5810GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
5811GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
5812GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
5813GEN_OP_SPE_LHE(le_64_user);
5814GEN_OP_SPE_LHE(le_64_kernel);
5815GEN_OP_SPE_LHE(le_64_hypv);
5816GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
5817GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
5818GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
5819GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
5820GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
5821GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
5822GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
5823GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
5824GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
5825GEN_OP_SPE_LHX(64_user);
5826GEN_OP_SPE_LHX(64_kernel);
5827GEN_OP_SPE_LHX(64_hypv);
5828GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
5829GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
5830GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
5831GEN_OP_SPE_LHX(le_64_user);
5832GEN_OP_SPE_LHX(le_64_kernel);
5833GEN_OP_SPE_LHX(le_64_hypv);
5834GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
5835GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
5836GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
5837#endif
5838#endif
5839GEN_SPEOP_LD(hhesplat, 1);
5840GEN_SPEOP_LD(hhousplat, 1);
5841GEN_SPEOP_LD(hhossplat, 1);
5842GEN_SPEOP_LD(wwsplat, 2);
5843GEN_SPEOP_LD(whsplat, 2);
5844
5845GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
5846GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
5847GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
5848GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
5849GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
5850GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
5851GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
5852GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
5853GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
5854GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
5855GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
5856GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
5857GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
5858GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
5859GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
5860GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
5861GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
5862GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
5863
5864/* Multiply and add - TODO */
5865#if 0
5866GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
5867GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
5868GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
5869GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
5870GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
5871GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
5872GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
5873GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
5874GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
5875GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
5876GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
5877GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
5878
5879GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
5880GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
5881GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
5882GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
5883GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
5884GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
5885GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
5886GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
5887GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
5888GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
5889GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
5890GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
5891GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
5892GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
5893
5894GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
5895GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
5896GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
5897GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
5898GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
5899GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
5900
5901GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
5902GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
5903GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
5904GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
5905GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
5906GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
5907GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
5908GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
5909GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
5910GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
5911GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
5912GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
5913
5914GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
5915GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
5916GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
5917GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
5918GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
5919
5920GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
5921GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
5922GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
5923GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
5924GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
5925GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
5926GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
5927GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
5928GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
5929GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
5930GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
5931GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
5932
5933GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
5934GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
5935GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
5936GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
5937GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
5938#endif
5939
5940/*** SPE floating-point extension ***/
5941#define GEN_SPEFPUOP_CONV(name) \
5942static always_inline void gen_##name (DisasContext *ctx) \
5943{ \
5944 gen_load_gpr64(cpu_T64[0], rB(ctx->opcode)); \
5945 gen_op_##name(); \
5946 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5947}
5948
5949/* Single precision floating-point vectors operations */
5950/* Arithmetic */
5951GEN_SPEOP_ARITH2(evfsadd);
5952GEN_SPEOP_ARITH2(evfssub);
5953GEN_SPEOP_ARITH2(evfsmul);
5954GEN_SPEOP_ARITH2(evfsdiv);
5955GEN_SPEOP_ARITH1(evfsabs);
5956GEN_SPEOP_ARITH1(evfsnabs);
5957GEN_SPEOP_ARITH1(evfsneg);
5958/* Conversion */
5959GEN_SPEFPUOP_CONV(evfscfui);
5960GEN_SPEFPUOP_CONV(evfscfsi);
5961GEN_SPEFPUOP_CONV(evfscfuf);
5962GEN_SPEFPUOP_CONV(evfscfsf);
5963GEN_SPEFPUOP_CONV(evfsctui);
5964GEN_SPEFPUOP_CONV(evfsctsi);
5965GEN_SPEFPUOP_CONV(evfsctuf);
5966GEN_SPEFPUOP_CONV(evfsctsf);
5967GEN_SPEFPUOP_CONV(evfsctuiz);
5968GEN_SPEFPUOP_CONV(evfsctsiz);
5969/* Comparison */
5970GEN_SPEOP_COMP(evfscmpgt);
5971GEN_SPEOP_COMP(evfscmplt);
5972GEN_SPEOP_COMP(evfscmpeq);
5973GEN_SPEOP_COMP(evfststgt);
5974GEN_SPEOP_COMP(evfststlt);
5975GEN_SPEOP_COMP(evfststeq);
5976
5977/* Opcodes definitions */
5978GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
5979GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
5980GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
5981GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
5982GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
5983GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
5984GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
5985GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
5986GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
5987GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
5988GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
5989GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
5990GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
5991GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
5992
5993/* Single precision floating-point operations */
5994/* Arithmetic */
5995GEN_SPEOP_ARITH2(efsadd);
5996GEN_SPEOP_ARITH2(efssub);
5997GEN_SPEOP_ARITH2(efsmul);
5998GEN_SPEOP_ARITH2(efsdiv);
5999GEN_SPEOP_ARITH1(efsabs);
6000GEN_SPEOP_ARITH1(efsnabs);
6001GEN_SPEOP_ARITH1(efsneg);
6002/* Conversion */
6003GEN_SPEFPUOP_CONV(efscfui);
6004GEN_SPEFPUOP_CONV(efscfsi);
6005GEN_SPEFPUOP_CONV(efscfuf);
6006GEN_SPEFPUOP_CONV(efscfsf);
6007GEN_SPEFPUOP_CONV(efsctui);
6008GEN_SPEFPUOP_CONV(efsctsi);
6009GEN_SPEFPUOP_CONV(efsctuf);
6010GEN_SPEFPUOP_CONV(efsctsf);
6011GEN_SPEFPUOP_CONV(efsctuiz);
6012GEN_SPEFPUOP_CONV(efsctsiz);
6013GEN_SPEFPUOP_CONV(efscfd);
6014/* Comparison */
6015GEN_SPEOP_COMP(efscmpgt);
6016GEN_SPEOP_COMP(efscmplt);
6017GEN_SPEOP_COMP(efscmpeq);
6018GEN_SPEOP_COMP(efststgt);
6019GEN_SPEOP_COMP(efststlt);
6020GEN_SPEOP_COMP(efststeq);
6021
6022/* Opcodes definitions */
6023GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6024GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
6025GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
6026GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
6027GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
6028GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
6029GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
6030GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
6031GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
6032GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6033GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
6034GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6035GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
6036GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6037
6038/* Double precision floating-point operations */
6039/* Arithmetic */
6040GEN_SPEOP_ARITH2(efdadd);
6041GEN_SPEOP_ARITH2(efdsub);
6042GEN_SPEOP_ARITH2(efdmul);
6043GEN_SPEOP_ARITH2(efddiv);
6044GEN_SPEOP_ARITH1(efdabs);
6045GEN_SPEOP_ARITH1(efdnabs);
6046GEN_SPEOP_ARITH1(efdneg);
6047/* Conversion */
6048
6049GEN_SPEFPUOP_CONV(efdcfui);
6050GEN_SPEFPUOP_CONV(efdcfsi);
6051GEN_SPEFPUOP_CONV(efdcfuf);
6052GEN_SPEFPUOP_CONV(efdcfsf);
6053GEN_SPEFPUOP_CONV(efdctui);
6054GEN_SPEFPUOP_CONV(efdctsi);
6055GEN_SPEFPUOP_CONV(efdctuf);
6056GEN_SPEFPUOP_CONV(efdctsf);
6057GEN_SPEFPUOP_CONV(efdctuiz);
6058GEN_SPEFPUOP_CONV(efdctsiz);
6059GEN_SPEFPUOP_CONV(efdcfs);
6060GEN_SPEFPUOP_CONV(efdcfuid);
6061GEN_SPEFPUOP_CONV(efdcfsid);
6062GEN_SPEFPUOP_CONV(efdctuidz);
6063GEN_SPEFPUOP_CONV(efdctsidz);
6064/* Comparison */
6065GEN_SPEOP_COMP(efdcmpgt);
6066GEN_SPEOP_COMP(efdcmplt);
6067GEN_SPEOP_COMP(efdcmpeq);
6068GEN_SPEOP_COMP(efdtstgt);
6069GEN_SPEOP_COMP(efdtstlt);
6070GEN_SPEOP_COMP(efdtsteq);
6071
6072/* Opcodes definitions */
6073GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
6074GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
6075GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
6076GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
6077GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
6078GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
6079GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
6080GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
6081GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
6082GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
6083GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
6084GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
6085GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
6086GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
6087GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
6088GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
6089
6090/* End opcode list */
6091GEN_OPCODE_MARK(end);
6092
6093#include "translate_init.c"
6094#include "helper_regs.h"
6095
6096/*****************************************************************************/
6097/* Misc PowerPC helpers */
6098void cpu_dump_state (CPUState *env, FILE *f,
6099 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6100 int flags)
6101{
6102#define RGPL 4
6103#define RFPL 4
6104
6105 int i;
6106
6107 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
6108 env->nip, env->lr, env->ctr, hreg_load_xer(env));
6109 cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
6110 env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6111#if !defined(NO_TIMER_DUMP)
6112 cpu_fprintf(f, "TB %08x %08x "
6113#if !defined(CONFIG_USER_ONLY)
6114 "DECR %08x"
6115#endif
6116 "\n",
6117 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6118#if !defined(CONFIG_USER_ONLY)
6119 , cpu_ppc_load_decr(env)
6120#endif
6121 );
6122#endif
6123 for (i = 0; i < 32; i++) {
6124 if ((i & (RGPL - 1)) == 0)
6125 cpu_fprintf(f, "GPR%02d", i);
6126 cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6127 if ((i & (RGPL - 1)) == (RGPL - 1))
6128 cpu_fprintf(f, "\n");
6129 }
6130 cpu_fprintf(f, "CR ");
6131 for (i = 0; i < 8; i++)
6132 cpu_fprintf(f, "%01x", env->crf[i]);
6133 cpu_fprintf(f, " [");
6134 for (i = 0; i < 8; i++) {
6135 char a = '-';
6136 if (env->crf[i] & 0x08)
6137 a = 'L';
6138 else if (env->crf[i] & 0x04)
6139 a = 'G';
6140 else if (env->crf[i] & 0x02)
6141 a = 'E';
6142 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6143 }
6144 cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
6145 for (i = 0; i < 32; i++) {
6146 if ((i & (RFPL - 1)) == 0)
6147 cpu_fprintf(f, "FPR%02d", i);
6148 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6149 if ((i & (RFPL - 1)) == (RFPL - 1))
6150 cpu_fprintf(f, "\n");
6151 }
6152#if !defined(CONFIG_USER_ONLY)
6153 cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6154 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6155#endif
6156
6157#undef RGPL
6158#undef RFPL
6159}
6160
6161void cpu_dump_statistics (CPUState *env, FILE*f,
6162 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6163 int flags)
6164{
6165#if defined(DO_PPC_STATISTICS)
6166 opc_handler_t **t1, **t2, **t3, *handler;
6167 int op1, op2, op3;
6168
6169 t1 = env->opcodes;
6170 for (op1 = 0; op1 < 64; op1++) {
6171 handler = t1[op1];
6172 if (is_indirect_opcode(handler)) {
6173 t2 = ind_table(handler);
6174 for (op2 = 0; op2 < 32; op2++) {
6175 handler = t2[op2];
6176 if (is_indirect_opcode(handler)) {
6177 t3 = ind_table(handler);
6178 for (op3 = 0; op3 < 32; op3++) {
6179 handler = t3[op3];
6180 if (handler->count == 0)
6181 continue;
6182 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
6183 "%016llx %lld\n",
6184 op1, op2, op3, op1, (op3 << 5) | op2,
6185 handler->oname,
6186 handler->count, handler->count);
6187 }
6188 } else {
6189 if (handler->count == 0)
6190 continue;
6191 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
6192 "%016llx %lld\n",
6193 op1, op2, op1, op2, handler->oname,
6194 handler->count, handler->count);
6195 }
6196 }
6197 } else {
6198 if (handler->count == 0)
6199 continue;
6200 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
6201 op1, op1, handler->oname,
6202 handler->count, handler->count);
6203 }
6204 }
6205#endif
6206}
6207
6208/*****************************************************************************/
6209static always_inline void gen_intermediate_code_internal (CPUState *env,
6210 TranslationBlock *tb,
6211 int search_pc)
6212{
6213 DisasContext ctx, *ctxp = &ctx;
6214 opc_handler_t **table, *handler;
6215 target_ulong pc_start;
6216 uint16_t *gen_opc_end;
6217 int supervisor, little_endian;
6218 int j, lj = -1;
6219 int num_insns;
6220 int max_insns;
6221
6222 pc_start = tb->pc;
6223 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6224#if defined(OPTIMIZE_FPRF_UPDATE)
6225 gen_fprf_ptr = gen_fprf_buf;
6226#endif
6227 ctx.nip = pc_start;
6228 ctx.tb = tb;
6229 ctx.exception = POWERPC_EXCP_NONE;
6230 ctx.spr_cb = env->spr_cb;
6231 supervisor = env->mmu_idx;
6232#if !defined(CONFIG_USER_ONLY)
6233 ctx.supervisor = supervisor;
6234#endif
6235 little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6236#if defined(TARGET_PPC64)
6237 ctx.sf_mode = msr_sf;
6238 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6239#else
6240 ctx.mem_idx = (supervisor << 1) | little_endian;
6241#endif
6242 ctx.dcache_line_size = env->dcache_line_size;
6243 ctx.fpu_enabled = msr_fp;
6244 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6245 ctx.spe_enabled = msr_spe;
6246 else
6247 ctx.spe_enabled = 0;
6248 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
6249 ctx.altivec_enabled = msr_vr;
6250 else
6251 ctx.altivec_enabled = 0;
6252 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6253 ctx.singlestep_enabled = CPU_SINGLE_STEP;
6254 else
6255 ctx.singlestep_enabled = 0;
6256 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6257 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
6258 if (unlikely(env->singlestep_enabled))
6259 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6260#if defined (DO_SINGLE_STEP) && 0
6261 /* Single step trace mode */
6262 msr_se = 1;
6263#endif
6264 num_insns = 0;
6265 max_insns = tb->cflags & CF_COUNT_MASK;
6266 if (max_insns == 0)
6267 max_insns = CF_COUNT_MASK;
6268
6269 gen_icount_start();
6270 /* Set env in case of segfault during code fetch */
6271 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6272 if (unlikely(env->nb_breakpoints > 0)) {
6273 for (j = 0; j < env->nb_breakpoints; j++) {
6274 if (env->breakpoints[j] == ctx.nip) {
6275 gen_update_nip(&ctx, ctx.nip);
6276 gen_op_debug();
6277 break;
6278 }
6279 }
6280 }
6281 if (unlikely(search_pc)) {
6282 j = gen_opc_ptr - gen_opc_buf;
6283 if (lj < j) {
6284 lj++;
6285 while (lj < j)
6286 gen_opc_instr_start[lj++] = 0;
6287 gen_opc_pc[lj] = ctx.nip;
6288 gen_opc_instr_start[lj] = 1;
6289 gen_opc_icount[lj] = num_insns;
6290 }
6291 }
6292#if defined PPC_DEBUG_DISAS
6293 if (loglevel & CPU_LOG_TB_IN_ASM) {
6294 fprintf(logfile, "----------------\n");
6295 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6296 ctx.nip, supervisor, (int)msr_ir);
6297 }
6298#endif
6299 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
6300 gen_io_start();
6301 if (unlikely(little_endian)) {
6302 ctx.opcode = bswap32(ldl_code(ctx.nip));
6303 } else {
6304 ctx.opcode = ldl_code(ctx.nip);
6305 }
6306#if defined PPC_DEBUG_DISAS
6307 if (loglevel & CPU_LOG_TB_IN_ASM) {
6308 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6309 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6310 opc3(ctx.opcode), little_endian ? "little" : "big");
6311 }
6312#endif
6313 ctx.nip += 4;
6314 table = env->opcodes;
6315 num_insns++;
6316 handler = table[opc1(ctx.opcode)];
6317 if (is_indirect_opcode(handler)) {
6318 table = ind_table(handler);
6319 handler = table[opc2(ctx.opcode)];
6320 if (is_indirect_opcode(handler)) {
6321 table = ind_table(handler);
6322 handler = table[opc3(ctx.opcode)];
6323 }
6324 }
6325 /* Is opcode *REALLY* valid ? */
6326 if (unlikely(handler->handler == &gen_invalid)) {
6327 if (loglevel != 0) {
6328 fprintf(logfile, "invalid/unsupported opcode: "
6329 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6330 opc1(ctx.opcode), opc2(ctx.opcode),
6331 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6332 } else {
6333 printf("invalid/unsupported opcode: "
6334 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6335 opc1(ctx.opcode), opc2(ctx.opcode),
6336 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6337 }
6338 } else {
6339 if (unlikely((ctx.opcode & handler->inval) != 0)) {
6340 if (loglevel != 0) {
6341 fprintf(logfile, "invalid bits: %08x for opcode: "
6342 "%02x - %02x - %02x (%08x) " ADDRX "\n",
6343 ctx.opcode & handler->inval, opc1(ctx.opcode),
6344 opc2(ctx.opcode), opc3(ctx.opcode),
6345 ctx.opcode, ctx.nip - 4);
6346 } else {
6347 printf("invalid bits: %08x for opcode: "
6348 "%02x - %02x - %02x (%08x) " ADDRX "\n",
6349 ctx.opcode & handler->inval, opc1(ctx.opcode),
6350 opc2(ctx.opcode), opc3(ctx.opcode),
6351 ctx.opcode, ctx.nip - 4);
6352 }
6353 GEN_EXCP_INVAL(ctxp);
6354 break;
6355 }
6356 }
6357 (*(handler->handler))(&ctx);
6358#if defined(DO_PPC_STATISTICS)
6359 handler->count++;
6360#endif
6361 /* Check trace mode exceptions */
6362 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
6363 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
6364 ctx.exception != POWERPC_SYSCALL &&
6365 ctx.exception != POWERPC_EXCP_TRAP &&
6366 ctx.exception != POWERPC_EXCP_BRANCH)) {
6367 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6368 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
6369 (env->singlestep_enabled) ||
6370 num_insns >= max_insns)) {
6371 /* if we reach a page boundary or are single stepping, stop
6372 * generation
6373 */
6374 break;
6375 }
6376#if defined (DO_SINGLE_STEP)
6377 break;
6378#endif
6379 }
6380 if (tb->cflags & CF_LAST_IO)
6381 gen_io_end();
6382 if (ctx.exception == POWERPC_EXCP_NONE) {
6383 gen_goto_tb(&ctx, 0, ctx.nip);
6384 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6385 if (unlikely(env->singlestep_enabled)) {
6386 gen_update_nip(&ctx, ctx.nip);
6387 gen_op_debug();
6388 }
6389 /* Generate the return instruction */
6390 tcg_gen_exit_tb(0);
6391 }
6392 gen_icount_end(tb, num_insns);
6393 *gen_opc_ptr = INDEX_op_end;
6394 if (unlikely(search_pc)) {
6395 j = gen_opc_ptr - gen_opc_buf;
6396 lj++;
6397 while (lj <= j)
6398 gen_opc_instr_start[lj++] = 0;
6399 } else {
6400 tb->size = ctx.nip - pc_start;
6401 tb->icount = num_insns;
6402 }
6403#if defined(DEBUG_DISAS)
6404 if (loglevel & CPU_LOG_TB_CPU) {
6405 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
6406 cpu_dump_state(env, logfile, fprintf, 0);
6407 }
6408 if (loglevel & CPU_LOG_TB_IN_ASM) {
6409 int flags;
6410 flags = env->bfd_mach;
6411 flags |= little_endian << 16;
6412 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6413 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
6414 fprintf(logfile, "\n");
6415 }
6416#endif
6417}
6418
6419void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6420{
6421 gen_intermediate_code_internal(env, tb, 0);
6422}
6423
6424void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6425{
6426 gen_intermediate_code_internal(env, tb, 1);
6427}
6428
6429void gen_pc_load(CPUState *env, TranslationBlock *tb,
6430 unsigned long searched_pc, int pc_pos, void *puc)
6431{
6432 int type, c;
6433 /* for PPC, we need to look at the micro operation to get the
6434 * access type */
6435 env->nip = gen_opc_pc[pc_pos];
6436 c = gen_opc_buf[pc_pos];
6437 switch(c) {
6438#if defined(CONFIG_USER_ONLY)
6439#define CASE3(op)\
6440 case INDEX_op_ ## op ## _raw
6441#else
6442#define CASE3(op)\
6443 case INDEX_op_ ## op ## _user:\
6444 case INDEX_op_ ## op ## _kernel:\
6445 case INDEX_op_ ## op ## _hypv
6446#endif
6447
6448 CASE3(stfd):
6449 CASE3(stfs):
6450 CASE3(lfd):
6451 CASE3(lfs):
6452 type = ACCESS_FLOAT;
6453 break;
6454 CASE3(lwarx):
6455 type = ACCESS_RES;
6456 break;
6457 CASE3(stwcx):
6458 type = ACCESS_RES;
6459 break;
6460 CASE3(eciwx):
6461 CASE3(ecowx):
6462 type = ACCESS_EXT;
6463 break;
6464 default:
6465 type = ACCESS_INT;
6466 break;
6467 }
6468 env->access_type = type;
6469}