2 * PowerPC emulation for qemu: main translation routines.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
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.
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.
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
31 #include "qemu-common.h"
33 #define CPU_SINGLE_STEP 0x1
34 #define CPU_BRANCH_STEP 0x2
35 #define GDBSTUB_SINGLE_STEP 0x4
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
44 /*****************************************************************************/
45 /* Code translation helpers */
47 /* global register indexes */
49 static char cpu_reg_names[10*3 + 22*4
50 #if !defined(TARGET_PPC64)
54 static TCGv cpu_gpr[32];
55 #if !defined(TARGET_PPC64)
56 static TCGv cpu_gprh[32];
59 /* dyngen register indexes */
61 #if defined(TARGET_PPC64)
64 static TCGv cpu_T64[3];
67 #include "gen-icount.h"
69 void ppc_translate_init(void)
73 static int done_init = 0;
78 cpu_env = tcg_global_reg_new(TCG_TYPE_PTR, TCG_AREG0, "env");
79 #if TARGET_LONG_BITS > HOST_LONG_BITS
80 cpu_T[0] = tcg_global_mem_new(TCG_TYPE_TL,
81 TCG_AREG0, offsetof(CPUState, t0), "T0");
82 cpu_T[1] = tcg_global_mem_new(TCG_TYPE_TL,
83 TCG_AREG0, offsetof(CPUState, t1), "T1");
84 cpu_T[2] = tcg_global_mem_new(TCG_TYPE_TL,
85 TCG_AREG0, offsetof(CPUState, t2), "T2");
87 cpu_T[0] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG1, "T0");
88 cpu_T[1] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG2, "T1");
89 cpu_T[2] = tcg_global_reg_new(TCG_TYPE_TL, TCG_AREG3, "T2");
91 #if !defined(TARGET_PPC64)
92 cpu_T64[0] = tcg_global_mem_new(TCG_TYPE_I64,
93 TCG_AREG0, offsetof(CPUState, t0_64),
95 cpu_T64[1] = tcg_global_mem_new(TCG_TYPE_I64,
96 TCG_AREG0, offsetof(CPUState, t1_64),
98 cpu_T64[2] = tcg_global_mem_new(TCG_TYPE_I64,
99 TCG_AREG0, offsetof(CPUState, t2_64),
104 for (i = 0; i < 32; i++) {
105 sprintf(p, "r%d", i);
106 cpu_gpr[i] = tcg_global_mem_new(TCG_TYPE_TL, TCG_AREG0,
107 offsetof(CPUState, gpr[i]), p);
108 p += (i < 10) ? 3 : 4;
109 #if !defined(TARGET_PPC64)
110 sprintf(p, "r%dH", i);
111 cpu_gprh[i] = tcg_global_mem_new(TCG_TYPE_I32, TCG_AREG0,
112 offsetof(CPUState, gprh[i]), p);
113 p += (i < 10) ? 4 : 5;
117 /* register helpers */
119 #define DEF_HELPER(ret, name, params) tcg_register_helper(name, #name);
125 #if defined(OPTIMIZE_FPRF_UPDATE)
126 static uint16_t *gen_fprf_buf[OPC_BUF_SIZE];
127 static uint16_t **gen_fprf_ptr;
130 #define GEN8(func, NAME) \
131 static GenOpFunc *NAME ## _table [8] = { \
132 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
133 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
135 static always_inline void func (int n) \
137 NAME ## _table[n](); \
140 #define GEN16(func, NAME) \
141 static GenOpFunc *NAME ## _table [16] = { \
142 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
143 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
144 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
145 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
147 static always_inline void func (int n) \
149 NAME ## _table[n](); \
152 #define GEN32(func, NAME) \
153 static GenOpFunc *NAME ## _table [32] = { \
154 NAME ## 0, NAME ## 1, NAME ## 2, NAME ## 3, \
155 NAME ## 4, NAME ## 5, NAME ## 6, NAME ## 7, \
156 NAME ## 8, NAME ## 9, NAME ## 10, NAME ## 11, \
157 NAME ## 12, NAME ## 13, NAME ## 14, NAME ## 15, \
158 NAME ## 16, NAME ## 17, NAME ## 18, NAME ## 19, \
159 NAME ## 20, NAME ## 21, NAME ## 22, NAME ## 23, \
160 NAME ## 24, NAME ## 25, NAME ## 26, NAME ## 27, \
161 NAME ## 28, NAME ## 29, NAME ## 30, NAME ## 31, \
163 static always_inline void func (int n) \
165 NAME ## _table[n](); \
168 /* Condition register moves */
169 GEN8(gen_op_load_crf_T0, gen_op_load_crf_T0_crf);
170 GEN8(gen_op_load_crf_T1, gen_op_load_crf_T1_crf);
171 GEN8(gen_op_store_T0_crf, gen_op_store_T0_crf_crf);
173 GEN8(gen_op_store_T1_crf, gen_op_store_T1_crf_crf);
176 /* floating point registers moves */
177 GEN32(gen_op_load_fpr_FT0, gen_op_load_fpr_FT0_fpr);
178 GEN32(gen_op_load_fpr_FT1, gen_op_load_fpr_FT1_fpr);
179 GEN32(gen_op_load_fpr_FT2, gen_op_load_fpr_FT2_fpr);
180 GEN32(gen_op_store_FT0_fpr, gen_op_store_FT0_fpr_fpr);
181 GEN32(gen_op_store_FT1_fpr, gen_op_store_FT1_fpr_fpr);
183 GEN32(gen_op_store_FT2_fpr, gen_op_store_FT2_fpr_fpr);
186 /* internal defines */
187 typedef struct DisasContext {
188 struct TranslationBlock *tb;
192 /* Routine used to access memory */
194 /* Translation flags */
195 #if !defined(CONFIG_USER_ONLY)
198 #if defined(TARGET_PPC64)
204 ppc_spr_t *spr_cb; /* Needed to check rights for mfspr/mtspr */
205 int singlestep_enabled;
206 int dcache_line_size;
209 struct opc_handler_t {
212 /* instruction type */
215 void (*handler)(DisasContext *ctx);
216 #if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
217 const unsigned char *oname;
219 #if defined(DO_PPC_STATISTICS)
224 static always_inline void gen_set_Rc0 (DisasContext *ctx)
226 #if defined(TARGET_PPC64)
235 static always_inline void gen_reset_fpstatus (void)
237 #ifdef CONFIG_SOFTFLOAT
238 gen_op_reset_fpstatus();
242 static always_inline void gen_compute_fprf (int set_fprf, int set_rc)
245 /* This case might be optimized later */
246 #if defined(OPTIMIZE_FPRF_UPDATE)
247 *gen_fprf_ptr++ = gen_opc_ptr;
249 gen_op_compute_fprf(1);
250 if (unlikely(set_rc))
251 gen_op_store_T0_crf(1);
252 gen_op_float_check_status();
253 } else if (unlikely(set_rc)) {
254 /* We always need to compute fpcc */
255 gen_op_compute_fprf(0);
256 gen_op_store_T0_crf(1);
258 gen_op_float_check_status();
262 static always_inline void gen_optimize_fprf (void)
264 #if defined(OPTIMIZE_FPRF_UPDATE)
267 for (ptr = gen_fprf_buf; ptr != (gen_fprf_ptr - 1); ptr++)
268 *ptr = INDEX_op_nop1;
269 gen_fprf_ptr = gen_fprf_buf;
273 static always_inline void gen_update_nip (DisasContext *ctx, target_ulong nip)
275 #if defined(TARGET_PPC64)
277 gen_op_update_nip_64(nip >> 32, nip);
280 gen_op_update_nip(nip);
283 #define GEN_EXCP(ctx, excp, error) \
285 if ((ctx)->exception == POWERPC_EXCP_NONE) { \
286 gen_update_nip(ctx, (ctx)->nip); \
288 gen_op_raise_exception_err((excp), (error)); \
289 ctx->exception = (excp); \
292 #define GEN_EXCP_INVAL(ctx) \
293 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
294 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL)
296 #define GEN_EXCP_PRIVOPC(ctx) \
297 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
298 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_OPC)
300 #define GEN_EXCP_PRIVREG(ctx) \
301 GEN_EXCP((ctx), POWERPC_EXCP_PROGRAM, \
302 POWERPC_EXCP_INVAL | POWERPC_EXCP_PRIV_REG)
304 #define GEN_EXCP_NO_FP(ctx) \
305 GEN_EXCP(ctx, POWERPC_EXCP_FPU, 0)
307 #define GEN_EXCP_NO_AP(ctx) \
308 GEN_EXCP(ctx, POWERPC_EXCP_APU, 0)
310 #define GEN_EXCP_NO_VR(ctx) \
311 GEN_EXCP(ctx, POWERPC_EXCP_VPU, 0)
313 /* Stop translation */
314 static always_inline void GEN_STOP (DisasContext *ctx)
316 gen_update_nip(ctx, ctx->nip);
317 ctx->exception = POWERPC_EXCP_STOP;
320 /* No need to update nip here, as execution flow will change */
321 static always_inline void GEN_SYNC (DisasContext *ctx)
323 ctx->exception = POWERPC_EXCP_SYNC;
326 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
327 static void gen_##name (DisasContext *ctx); \
328 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
329 static void gen_##name (DisasContext *ctx)
331 #define GEN_HANDLER2(name, onam, opc1, opc2, opc3, inval, type) \
332 static void gen_##name (DisasContext *ctx); \
333 GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type); \
334 static void gen_##name (DisasContext *ctx)
336 typedef struct opcode_t {
337 unsigned char opc1, opc2, opc3;
338 #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
339 unsigned char pad[5];
341 unsigned char pad[1];
343 opc_handler_t handler;
344 const unsigned char *oname;
347 /*****************************************************************************/
348 /*** Instruction decoding ***/
349 #define EXTRACT_HELPER(name, shift, nb) \
350 static always_inline uint32_t name (uint32_t opcode) \
352 return (opcode >> (shift)) & ((1 << (nb)) - 1); \
355 #define EXTRACT_SHELPER(name, shift, nb) \
356 static always_inline int32_t name (uint32_t opcode) \
358 return (int16_t)((opcode >> (shift)) & ((1 << (nb)) - 1)); \
362 EXTRACT_HELPER(opc1, 26, 6);
364 EXTRACT_HELPER(opc2, 1, 5);
366 EXTRACT_HELPER(opc3, 6, 5);
367 /* Update Cr0 flags */
368 EXTRACT_HELPER(Rc, 0, 1);
370 EXTRACT_HELPER(rD, 21, 5);
372 EXTRACT_HELPER(rS, 21, 5);
374 EXTRACT_HELPER(rA, 16, 5);
376 EXTRACT_HELPER(rB, 11, 5);
378 EXTRACT_HELPER(rC, 6, 5);
380 EXTRACT_HELPER(crfD, 23, 3);
381 EXTRACT_HELPER(crfS, 18, 3);
382 EXTRACT_HELPER(crbD, 21, 5);
383 EXTRACT_HELPER(crbA, 16, 5);
384 EXTRACT_HELPER(crbB, 11, 5);
386 EXTRACT_HELPER(_SPR, 11, 10);
387 static always_inline uint32_t SPR (uint32_t opcode)
389 uint32_t sprn = _SPR(opcode);
391 return ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
393 /*** Get constants ***/
394 EXTRACT_HELPER(IMM, 12, 8);
395 /* 16 bits signed immediate value */
396 EXTRACT_SHELPER(SIMM, 0, 16);
397 /* 16 bits unsigned immediate value */
398 EXTRACT_HELPER(UIMM, 0, 16);
400 EXTRACT_HELPER(NB, 11, 5);
402 EXTRACT_HELPER(SH, 11, 5);
404 EXTRACT_HELPER(MB, 6, 5);
406 EXTRACT_HELPER(ME, 1, 5);
408 EXTRACT_HELPER(TO, 21, 5);
410 EXTRACT_HELPER(CRM, 12, 8);
411 EXTRACT_HELPER(FM, 17, 8);
412 EXTRACT_HELPER(SR, 16, 4);
413 EXTRACT_HELPER(FPIMM, 12, 4);
415 /*** Jump target decoding ***/
417 EXTRACT_SHELPER(d, 0, 16);
418 /* Immediate address */
419 static always_inline target_ulong LI (uint32_t opcode)
421 return (opcode >> 0) & 0x03FFFFFC;
424 static always_inline uint32_t BD (uint32_t opcode)
426 return (opcode >> 0) & 0xFFFC;
429 EXTRACT_HELPER(BO, 21, 5);
430 EXTRACT_HELPER(BI, 16, 5);
431 /* Absolute/relative address */
432 EXTRACT_HELPER(AA, 1, 1);
434 EXTRACT_HELPER(LK, 0, 1);
436 /* Create a mask between <start> and <end> bits */
437 static always_inline target_ulong MASK (uint32_t start, uint32_t end)
441 #if defined(TARGET_PPC64)
442 if (likely(start == 0)) {
443 ret = UINT64_MAX << (63 - end);
444 } else if (likely(end == 63)) {
445 ret = UINT64_MAX >> start;
448 if (likely(start == 0)) {
449 ret = UINT32_MAX << (31 - end);
450 } else if (likely(end == 31)) {
451 ret = UINT32_MAX >> start;
455 ret = (((target_ulong)(-1ULL)) >> (start)) ^
456 (((target_ulong)(-1ULL) >> (end)) >> 1);
457 if (unlikely(start > end))
464 /*****************************************************************************/
465 /* PowerPC Instructions types definitions */
467 PPC_NONE = 0x0000000000000000ULL,
468 /* PowerPC base instructions set */
469 PPC_INSNS_BASE = 0x0000000000000001ULL,
470 /* integer operations instructions */
471 #define PPC_INTEGER PPC_INSNS_BASE
472 /* flow control instructions */
473 #define PPC_FLOW PPC_INSNS_BASE
474 /* virtual memory instructions */
475 #define PPC_MEM PPC_INSNS_BASE
476 /* ld/st with reservation instructions */
477 #define PPC_RES PPC_INSNS_BASE
478 /* spr/msr access instructions */
479 #define PPC_MISC PPC_INSNS_BASE
480 /* Deprecated instruction sets */
481 /* Original POWER instruction set */
482 PPC_POWER = 0x0000000000000002ULL,
483 /* POWER2 instruction set extension */
484 PPC_POWER2 = 0x0000000000000004ULL,
485 /* Power RTC support */
486 PPC_POWER_RTC = 0x0000000000000008ULL,
487 /* Power-to-PowerPC bridge (601) */
488 PPC_POWER_BR = 0x0000000000000010ULL,
489 /* 64 bits PowerPC instruction set */
490 PPC_64B = 0x0000000000000020ULL,
491 /* New 64 bits extensions (PowerPC 2.0x) */
492 PPC_64BX = 0x0000000000000040ULL,
493 /* 64 bits hypervisor extensions */
494 PPC_64H = 0x0000000000000080ULL,
495 /* New wait instruction (PowerPC 2.0x) */
496 PPC_WAIT = 0x0000000000000100ULL,
497 /* Time base mftb instruction */
498 PPC_MFTB = 0x0000000000000200ULL,
500 /* Fixed-point unit extensions */
501 /* PowerPC 602 specific */
502 PPC_602_SPEC = 0x0000000000000400ULL,
503 /* isel instruction */
504 PPC_ISEL = 0x0000000000000800ULL,
505 /* popcntb instruction */
506 PPC_POPCNTB = 0x0000000000001000ULL,
507 /* string load / store */
508 PPC_STRING = 0x0000000000002000ULL,
510 /* Floating-point unit extensions */
511 /* Optional floating point instructions */
512 PPC_FLOAT = 0x0000000000010000ULL,
513 /* New floating-point extensions (PowerPC 2.0x) */
514 PPC_FLOAT_EXT = 0x0000000000020000ULL,
515 PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
516 PPC_FLOAT_FRES = 0x0000000000080000ULL,
517 PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
518 PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
519 PPC_FLOAT_FSEL = 0x0000000000400000ULL,
520 PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
522 /* Vector/SIMD extensions */
523 /* Altivec support */
524 PPC_ALTIVEC = 0x0000000001000000ULL,
525 /* PowerPC 2.03 SPE extension */
526 PPC_SPE = 0x0000000002000000ULL,
527 /* PowerPC 2.03 SPE floating-point extension */
528 PPC_SPEFPU = 0x0000000004000000ULL,
530 /* Optional memory control instructions */
531 PPC_MEM_TLBIA = 0x0000000010000000ULL,
532 PPC_MEM_TLBIE = 0x0000000020000000ULL,
533 PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
534 /* sync instruction */
535 PPC_MEM_SYNC = 0x0000000080000000ULL,
536 /* eieio instruction */
537 PPC_MEM_EIEIO = 0x0000000100000000ULL,
539 /* Cache control instructions */
540 PPC_CACHE = 0x0000000200000000ULL,
541 /* icbi instruction */
542 PPC_CACHE_ICBI = 0x0000000400000000ULL,
543 /* dcbz instruction with fixed cache line size */
544 PPC_CACHE_DCBZ = 0x0000000800000000ULL,
545 /* dcbz instruction with tunable cache line size */
546 PPC_CACHE_DCBZT = 0x0000001000000000ULL,
547 /* dcba instruction */
548 PPC_CACHE_DCBA = 0x0000002000000000ULL,
549 /* Freescale cache locking instructions */
550 PPC_CACHE_LOCK = 0x0000004000000000ULL,
552 /* MMU related extensions */
553 /* external control instructions */
554 PPC_EXTERN = 0x0000010000000000ULL,
555 /* segment register access instructions */
556 PPC_SEGMENT = 0x0000020000000000ULL,
557 /* PowerPC 6xx TLB management instructions */
558 PPC_6xx_TLB = 0x0000040000000000ULL,
559 /* PowerPC 74xx TLB management instructions */
560 PPC_74xx_TLB = 0x0000080000000000ULL,
561 /* PowerPC 40x TLB management instructions */
562 PPC_40x_TLB = 0x0000100000000000ULL,
563 /* segment register access instructions for PowerPC 64 "bridge" */
564 PPC_SEGMENT_64B = 0x0000200000000000ULL,
566 PPC_SLBI = 0x0000400000000000ULL,
568 /* Embedded PowerPC dedicated instructions */
569 PPC_WRTEE = 0x0001000000000000ULL,
570 /* PowerPC 40x exception model */
571 PPC_40x_EXCP = 0x0002000000000000ULL,
572 /* PowerPC 405 Mac instructions */
573 PPC_405_MAC = 0x0004000000000000ULL,
574 /* PowerPC 440 specific instructions */
575 PPC_440_SPEC = 0x0008000000000000ULL,
576 /* BookE (embedded) PowerPC specification */
577 PPC_BOOKE = 0x0010000000000000ULL,
578 /* mfapidi instruction */
579 PPC_MFAPIDI = 0x0020000000000000ULL,
580 /* tlbiva instruction */
581 PPC_TLBIVA = 0x0040000000000000ULL,
582 /* tlbivax instruction */
583 PPC_TLBIVAX = 0x0080000000000000ULL,
584 /* PowerPC 4xx dedicated instructions */
585 PPC_4xx_COMMON = 0x0100000000000000ULL,
586 /* PowerPC 40x ibct instructions */
587 PPC_40x_ICBT = 0x0200000000000000ULL,
588 /* rfmci is not implemented in all BookE PowerPC */
589 PPC_RFMCI = 0x0400000000000000ULL,
590 /* rfdi instruction */
591 PPC_RFDI = 0x0800000000000000ULL,
593 PPC_DCR = 0x1000000000000000ULL,
594 /* DCR extended accesse */
595 PPC_DCRX = 0x2000000000000000ULL,
596 /* user-mode DCR access, implemented in PowerPC 460 */
597 PPC_DCRUX = 0x4000000000000000ULL,
600 /*****************************************************************************/
601 /* PowerPC instructions table */
602 #if HOST_LONG_BITS == 64
607 #if defined(__APPLE__)
608 #define OPCODES_SECTION \
609 __attribute__ ((section("__TEXT,__opcodes"), unused, aligned (OPC_ALIGN) ))
611 #define OPCODES_SECTION \
612 __attribute__ ((section(".opcodes"), unused, aligned (OPC_ALIGN) ))
615 #if defined(DO_PPC_STATISTICS)
616 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
617 OPCODES_SECTION opcode_t opc_##name = { \
625 .handler = &gen_##name, \
626 .oname = stringify(name), \
628 .oname = stringify(name), \
630 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
631 OPCODES_SECTION opcode_t opc_##name = { \
639 .handler = &gen_##name, \
645 #define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
646 OPCODES_SECTION opcode_t opc_##name = { \
654 .handler = &gen_##name, \
656 .oname = stringify(name), \
658 #define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
659 OPCODES_SECTION opcode_t opc_##name = { \
667 .handler = &gen_##name, \
673 #define GEN_OPCODE_MARK(name) \
674 OPCODES_SECTION opcode_t opc_##name = { \
680 .inval = 0x00000000, \
684 .oname = stringify(name), \
687 /* Start opcode list */
688 GEN_OPCODE_MARK(start);
690 /* Invalid instruction */
691 GEN_HANDLER(invalid, 0x00, 0x00, 0x00, 0xFFFFFFFF, PPC_NONE)
696 static opc_handler_t invalid_handler = {
699 .handler = gen_invalid,
702 /*** Integer arithmetic ***/
703 #define __GEN_INT_ARITH2(name, opc1, opc2, opc3, inval, type) \
704 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
706 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
707 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
709 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
710 if (unlikely(Rc(ctx->opcode) != 0)) \
714 #define __GEN_INT_ARITH2_O(name, opc1, opc2, opc3, inval, type) \
715 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
717 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
718 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
720 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
721 if (unlikely(Rc(ctx->opcode) != 0)) \
725 #define __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
726 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
728 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
730 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
731 if (unlikely(Rc(ctx->opcode) != 0)) \
734 #define __GEN_INT_ARITH1_O(name, opc1, opc2, opc3, type) \
735 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
737 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
739 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
740 if (unlikely(Rc(ctx->opcode) != 0)) \
744 /* Two operands arithmetic functions */
745 #define GEN_INT_ARITH2(name, opc1, opc2, opc3, type) \
746 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000000, type) \
747 __GEN_INT_ARITH2_O(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
749 /* Two operands arithmetic functions with no overflow allowed */
750 #define GEN_INT_ARITHN(name, opc1, opc2, opc3, type) \
751 __GEN_INT_ARITH2(name, opc1, opc2, opc3, 0x00000400, type)
753 /* One operand arithmetic functions */
754 #define GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
755 __GEN_INT_ARITH1(name, opc1, opc2, opc3, type) \
756 __GEN_INT_ARITH1_O(name##o, opc1, opc2, opc3 | 0x10, type)
758 #if defined(TARGET_PPC64)
759 #define __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, inval, type) \
760 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
762 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
763 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
765 gen_op_##name##_64(); \
768 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
769 if (unlikely(Rc(ctx->opcode) != 0)) \
773 #define __GEN_INT_ARITH2_O_64(name, opc1, opc2, opc3, inval, type) \
774 GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
776 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
777 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
779 gen_op_##name##_64(); \
782 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
783 if (unlikely(Rc(ctx->opcode) != 0)) \
787 #define __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
788 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
790 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
792 gen_op_##name##_64(); \
795 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
796 if (unlikely(Rc(ctx->opcode) != 0)) \
799 #define __GEN_INT_ARITH1_O_64(name, opc1, opc2, opc3, type) \
800 GEN_HANDLER(name, opc1, opc2, opc3, 0x0000F800, type) \
802 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
804 gen_op_##name##_64(); \
807 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]); \
808 if (unlikely(Rc(ctx->opcode) != 0)) \
812 /* Two operands arithmetic functions */
813 #define GEN_INT_ARITH2_64(name, opc1, opc2, opc3, type) \
814 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000000, type) \
815 __GEN_INT_ARITH2_O_64(name##o, opc1, opc2, opc3 | 0x10, 0x00000000, type)
817 /* Two operands arithmetic functions with no overflow allowed */
818 #define GEN_INT_ARITHN_64(name, opc1, opc2, opc3, type) \
819 __GEN_INT_ARITH2_64(name, opc1, opc2, opc3, 0x00000400, type)
821 /* One operand arithmetic functions */
822 #define GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
823 __GEN_INT_ARITH1_64(name, opc1, opc2, opc3, type) \
824 __GEN_INT_ARITH1_O_64(name##o, opc1, opc2, opc3 | 0x10, type)
826 #define GEN_INT_ARITH2_64 GEN_INT_ARITH2
827 #define GEN_INT_ARITHN_64 GEN_INT_ARITHN
828 #define GEN_INT_ARITH1_64 GEN_INT_ARITH1
831 /* add add. addo addo. */
832 static always_inline void gen_op_addo (void)
834 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
838 #if defined(TARGET_PPC64)
839 #define gen_op_add_64 gen_op_add
840 static always_inline void gen_op_addo_64 (void)
842 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
844 gen_op_check_addo_64();
847 GEN_INT_ARITH2_64 (add, 0x1F, 0x0A, 0x08, PPC_INTEGER);
848 /* addc addc. addco addco. */
849 static always_inline void gen_op_addc (void)
851 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
855 static always_inline void gen_op_addco (void)
857 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
862 #if defined(TARGET_PPC64)
863 static always_inline void gen_op_addc_64 (void)
865 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
867 gen_op_check_addc_64();
869 static always_inline void gen_op_addco_64 (void)
871 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
873 gen_op_check_addc_64();
874 gen_op_check_addo_64();
877 GEN_INT_ARITH2_64 (addc, 0x1F, 0x0A, 0x00, PPC_INTEGER);
878 /* adde adde. addeo addeo. */
879 static always_inline void gen_op_addeo (void)
881 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
885 #if defined(TARGET_PPC64)
886 static always_inline void gen_op_addeo_64 (void)
888 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
890 gen_op_check_addo_64();
893 GEN_INT_ARITH2_64 (adde, 0x1F, 0x0A, 0x04, PPC_INTEGER);
894 /* addme addme. addmeo addmeo. */
895 static always_inline void gen_op_addme (void)
897 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
900 #if defined(TARGET_PPC64)
901 static always_inline void gen_op_addme_64 (void)
903 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
907 GEN_INT_ARITH1_64 (addme, 0x1F, 0x0A, 0x07, PPC_INTEGER);
908 /* addze addze. addzeo addzeo. */
909 static always_inline void gen_op_addze (void)
911 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
915 static always_inline void gen_op_addzeo (void)
917 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
922 #if defined(TARGET_PPC64)
923 static always_inline void gen_op_addze_64 (void)
925 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
927 gen_op_check_addc_64();
929 static always_inline void gen_op_addzeo_64 (void)
931 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
933 gen_op_check_addc_64();
934 gen_op_check_addo_64();
937 GEN_INT_ARITH1_64 (addze, 0x1F, 0x0A, 0x06, PPC_INTEGER);
938 /* divw divw. divwo divwo. */
939 GEN_INT_ARITH2 (divw, 0x1F, 0x0B, 0x0F, PPC_INTEGER);
940 /* divwu divwu. divwuo divwuo. */
941 GEN_INT_ARITH2 (divwu, 0x1F, 0x0B, 0x0E, PPC_INTEGER);
943 GEN_INT_ARITHN (mulhw, 0x1F, 0x0B, 0x02, PPC_INTEGER);
945 GEN_INT_ARITHN (mulhwu, 0x1F, 0x0B, 0x00, PPC_INTEGER);
946 /* mullw mullw. mullwo mullwo. */
947 GEN_INT_ARITH2 (mullw, 0x1F, 0x0B, 0x07, PPC_INTEGER);
948 /* neg neg. nego nego. */
949 GEN_INT_ARITH1_64 (neg, 0x1F, 0x08, 0x03, PPC_INTEGER);
950 /* subf subf. subfo subfo. */
951 static always_inline void gen_op_subfo (void)
953 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
957 #if defined(TARGET_PPC64)
958 #define gen_op_subf_64 gen_op_subf
959 static always_inline void gen_op_subfo_64 (void)
961 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
963 gen_op_check_addo_64();
966 GEN_INT_ARITH2_64 (subf, 0x1F, 0x08, 0x01, PPC_INTEGER);
967 /* subfc subfc. subfco subfco. */
968 static always_inline void gen_op_subfc (void)
971 gen_op_check_subfc();
973 static always_inline void gen_op_subfco (void)
975 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
977 gen_op_check_subfc();
980 #if defined(TARGET_PPC64)
981 static always_inline void gen_op_subfc_64 (void)
984 gen_op_check_subfc_64();
986 static always_inline void gen_op_subfco_64 (void)
988 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
990 gen_op_check_subfc_64();
991 gen_op_check_addo_64();
994 GEN_INT_ARITH2_64 (subfc, 0x1F, 0x08, 0x00, PPC_INTEGER);
995 /* subfe subfe. subfeo subfeo. */
996 static always_inline void gen_op_subfeo (void)
998 tcg_gen_not_tl(cpu_T[2], cpu_T[0]);
1000 gen_op_check_addo();
1002 #if defined(TARGET_PPC64)
1003 #define gen_op_subfe_64 gen_op_subfe
1004 static always_inline void gen_op_subfeo_64 (void)
1006 tcg_gen_not_i64(cpu_T[2], cpu_T[0]);
1008 gen_op_check_addo_64();
1011 GEN_INT_ARITH2_64 (subfe, 0x1F, 0x08, 0x04, PPC_INTEGER);
1012 /* subfme subfme. subfmeo subfmeo. */
1013 GEN_INT_ARITH1_64 (subfme, 0x1F, 0x08, 0x07, PPC_INTEGER);
1014 /* subfze subfze. subfzeo subfzeo. */
1015 GEN_INT_ARITH1_64 (subfze, 0x1F, 0x08, 0x06, PPC_INTEGER);
1017 GEN_HANDLER(addi, 0x0E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1019 target_long simm = SIMM(ctx->opcode);
1021 if (rA(ctx->opcode) == 0) {
1023 tcg_gen_movi_tl(cpu_T[0], simm);
1025 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1026 if (likely(simm != 0))
1029 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1032 GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1034 target_long simm = SIMM(ctx->opcode);
1036 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1037 if (likely(simm != 0)) {
1038 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1040 #if defined(TARGET_PPC64)
1042 gen_op_check_addc_64();
1045 gen_op_check_addc();
1047 gen_op_clear_xer_ca();
1049 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1052 GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1054 target_long simm = SIMM(ctx->opcode);
1056 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1057 if (likely(simm != 0)) {
1058 tcg_gen_mov_tl(cpu_T[2], cpu_T[0]);
1060 #if defined(TARGET_PPC64)
1062 gen_op_check_addc_64();
1065 gen_op_check_addc();
1067 gen_op_clear_xer_ca();
1069 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1073 GEN_HANDLER(addis, 0x0F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1075 target_long simm = SIMM(ctx->opcode);
1077 if (rA(ctx->opcode) == 0) {
1079 tcg_gen_movi_tl(cpu_T[0], simm << 16);
1081 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1082 if (likely(simm != 0))
1083 gen_op_addi(simm << 16);
1085 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1088 GEN_HANDLER(mulli, 0x07, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1090 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1091 gen_op_mulli(SIMM(ctx->opcode));
1092 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1095 GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1097 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1098 #if defined(TARGET_PPC64)
1100 gen_op_subfic_64(SIMM(ctx->opcode));
1103 gen_op_subfic(SIMM(ctx->opcode));
1104 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1107 #if defined(TARGET_PPC64)
1109 GEN_INT_ARITHN (mulhd, 0x1F, 0x09, 0x02, PPC_64B);
1110 /* mulhdu mulhdu. */
1111 GEN_INT_ARITHN (mulhdu, 0x1F, 0x09, 0x00, PPC_64B);
1112 /* mulld mulld. mulldo mulldo. */
1113 GEN_INT_ARITH2 (mulld, 0x1F, 0x09, 0x07, PPC_64B);
1114 /* divd divd. divdo divdo. */
1115 GEN_INT_ARITH2 (divd, 0x1F, 0x09, 0x0F, PPC_64B);
1116 /* divdu divdu. divduo divduo. */
1117 GEN_INT_ARITH2 (divdu, 0x1F, 0x09, 0x0E, PPC_64B);
1120 /*** Integer comparison ***/
1121 #if defined(TARGET_PPC64)
1122 #define GEN_CMP(name, opc, type) \
1123 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1125 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
1126 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1127 if (ctx->sf_mode && (ctx->opcode & 0x00200000)) \
1128 gen_op_##name##_64(); \
1131 gen_op_store_T0_crf(crfD(ctx->opcode)); \
1134 #define GEN_CMP(name, opc, type) \
1135 GEN_HANDLER(name, 0x1F, 0x00, opc, 0x00400000, type) \
1137 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]); \
1138 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1140 gen_op_store_T0_crf(crfD(ctx->opcode)); \
1145 GEN_CMP(cmp, 0x00, PPC_INTEGER);
1147 GEN_HANDLER(cmpi, 0x0B, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1149 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1150 #if defined(TARGET_PPC64)
1151 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1152 gen_op_cmpi_64(SIMM(ctx->opcode));
1155 gen_op_cmpi(SIMM(ctx->opcode));
1156 gen_op_store_T0_crf(crfD(ctx->opcode));
1159 GEN_CMP(cmpl, 0x01, PPC_INTEGER);
1161 GEN_HANDLER(cmpli, 0x0A, 0xFF, 0xFF, 0x00400000, PPC_INTEGER)
1163 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1164 #if defined(TARGET_PPC64)
1165 if (ctx->sf_mode && (ctx->opcode & 0x00200000))
1166 gen_op_cmpli_64(UIMM(ctx->opcode));
1169 gen_op_cmpli(UIMM(ctx->opcode));
1170 gen_op_store_T0_crf(crfD(ctx->opcode));
1173 /* isel (PowerPC 2.03 specification) */
1174 GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL)
1176 uint32_t bi = rC(ctx->opcode);
1179 if (rA(ctx->opcode) == 0) {
1180 tcg_gen_movi_tl(cpu_T[0], 0);
1182 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1184 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
1185 mask = 1 << (3 - (bi & 0x03));
1186 gen_op_load_crf_T0(bi >> 2);
1187 gen_op_test_true(mask);
1189 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
1192 /*** Integer logical ***/
1193 #define __GEN_LOGICAL2(name, opc2, opc3, type) \
1194 GEN_HANDLER(name, 0x1F, opc2, opc3, 0x00000000, type) \
1196 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); \
1197 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]); \
1199 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
1200 if (unlikely(Rc(ctx->opcode) != 0)) \
1203 #define GEN_LOGICAL2(name, opc, type) \
1204 __GEN_LOGICAL2(name, 0x1C, opc, type)
1206 #define GEN_LOGICAL1(name, opc, type) \
1207 GEN_HANDLER(name, 0x1F, 0x1A, opc, 0x00000000, type) \
1209 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]); \
1211 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
1212 if (unlikely(Rc(ctx->opcode) != 0)) \
1217 GEN_LOGICAL2(and, 0x00, PPC_INTEGER);
1219 GEN_LOGICAL2(andc, 0x01, PPC_INTEGER);
1221 GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1223 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1224 gen_op_andi_T0(UIMM(ctx->opcode));
1225 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1229 GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1231 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1232 gen_op_andi_T0(UIMM(ctx->opcode) << 16);
1233 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1238 GEN_LOGICAL1(cntlzw, 0x00, PPC_INTEGER);
1240 GEN_LOGICAL2(eqv, 0x08, PPC_INTEGER);
1241 /* extsb & extsb. */
1242 GEN_LOGICAL1(extsb, 0x1D, PPC_INTEGER);
1243 /* extsh & extsh. */
1244 GEN_LOGICAL1(extsh, 0x1C, PPC_INTEGER);
1246 GEN_LOGICAL2(nand, 0x0E, PPC_INTEGER);
1248 GEN_LOGICAL2(nor, 0x03, PPC_INTEGER);
1251 GEN_HANDLER(or, 0x1F, 0x1C, 0x0D, 0x00000000, PPC_INTEGER)
1255 rs = rS(ctx->opcode);
1256 ra = rA(ctx->opcode);
1257 rb = rB(ctx->opcode);
1258 /* Optimisation for mr. ri case */
1259 if (rs != ra || rs != rb) {
1260 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1262 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
1265 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
1266 if (unlikely(Rc(ctx->opcode) != 0))
1268 } else if (unlikely(Rc(ctx->opcode) != 0)) {
1269 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rs]);
1271 #if defined(TARGET_PPC64)
1275 /* Set process priority to low */
1276 gen_op_store_pri(2);
1279 /* Set process priority to medium-low */
1280 gen_op_store_pri(3);
1283 /* Set process priority to normal */
1284 gen_op_store_pri(4);
1286 #if !defined(CONFIG_USER_ONLY)
1288 if (ctx->supervisor > 0) {
1289 /* Set process priority to very low */
1290 gen_op_store_pri(1);
1294 if (ctx->supervisor > 0) {
1295 /* Set process priority to medium-hight */
1296 gen_op_store_pri(5);
1300 if (ctx->supervisor > 0) {
1301 /* Set process priority to high */
1302 gen_op_store_pri(6);
1306 if (ctx->supervisor > 1) {
1307 /* Set process priority to very high */
1308 gen_op_store_pri(7);
1321 GEN_LOGICAL2(orc, 0x0C, PPC_INTEGER);
1323 GEN_HANDLER(xor, 0x1F, 0x1C, 0x09, 0x00000000, PPC_INTEGER)
1325 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1326 /* Optimisation for "set to zero" case */
1327 if (rS(ctx->opcode) != rB(ctx->opcode)) {
1328 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1331 tcg_gen_movi_tl(cpu_T[0], 0);
1333 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1334 if (unlikely(Rc(ctx->opcode) != 0))
1338 GEN_HANDLER(ori, 0x18, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1340 target_ulong uimm = UIMM(ctx->opcode);
1342 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1344 /* XXX: should handle special NOPs for POWER series */
1347 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1348 if (likely(uimm != 0))
1350 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1353 GEN_HANDLER(oris, 0x19, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1355 target_ulong uimm = UIMM(ctx->opcode);
1357 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1361 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1362 if (likely(uimm != 0))
1363 gen_op_ori(uimm << 16);
1364 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1367 GEN_HANDLER(xori, 0x1A, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1369 target_ulong uimm = UIMM(ctx->opcode);
1371 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1375 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1376 if (likely(uimm != 0))
1378 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1382 GEN_HANDLER(xoris, 0x1B, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1384 target_ulong uimm = UIMM(ctx->opcode);
1386 if (rS(ctx->opcode) == rA(ctx->opcode) && uimm == 0) {
1390 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1391 if (likely(uimm != 0))
1392 gen_op_xori(uimm << 16);
1393 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1396 /* popcntb : PowerPC 2.03 specification */
1397 GEN_HANDLER(popcntb, 0x1F, 0x03, 0x03, 0x0000F801, PPC_POPCNTB)
1399 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1400 #if defined(TARGET_PPC64)
1402 gen_op_popcntb_64();
1406 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1409 #if defined(TARGET_PPC64)
1410 /* extsw & extsw. */
1411 GEN_LOGICAL1(extsw, 0x1E, PPC_64B);
1413 GEN_LOGICAL1(cntlzd, 0x01, PPC_64B);
1416 /*** Integer rotate ***/
1417 /* rlwimi & rlwimi. */
1418 GEN_HANDLER(rlwimi, 0x14, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1421 uint32_t mb, me, sh;
1423 mb = MB(ctx->opcode);
1424 me = ME(ctx->opcode);
1425 sh = SH(ctx->opcode);
1426 if (likely(sh == 0)) {
1427 if (likely(mb == 0 && me == 31)) {
1428 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1430 } else if (likely(mb == 31 && me == 0)) {
1431 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
1434 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1435 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1438 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1439 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1440 gen_op_rotli32_T0(SH(ctx->opcode));
1442 #if defined(TARGET_PPC64)
1446 mask = MASK(mb, me);
1447 gen_op_andi_T0(mask);
1448 gen_op_andi_T1(~mask);
1451 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1452 if (unlikely(Rc(ctx->opcode) != 0))
1455 /* rlwinm & rlwinm. */
1456 GEN_HANDLER(rlwinm, 0x15, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1458 uint32_t mb, me, sh;
1460 sh = SH(ctx->opcode);
1461 mb = MB(ctx->opcode);
1462 me = ME(ctx->opcode);
1463 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1464 if (likely(sh == 0)) {
1467 if (likely(mb == 0)) {
1468 if (likely(me == 31)) {
1469 gen_op_rotli32_T0(sh);
1471 } else if (likely(me == (31 - sh))) {
1475 } else if (likely(me == 31)) {
1476 if (likely(sh == (32 - mb))) {
1481 gen_op_rotli32_T0(sh);
1483 #if defined(TARGET_PPC64)
1487 gen_op_andi_T0(MASK(mb, me));
1489 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1490 if (unlikely(Rc(ctx->opcode) != 0))
1493 /* rlwnm & rlwnm. */
1494 GEN_HANDLER(rlwnm, 0x17, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
1498 mb = MB(ctx->opcode);
1499 me = ME(ctx->opcode);
1500 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1501 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1502 gen_op_rotl32_T0_T1();
1503 if (unlikely(mb != 0 || me != 31)) {
1504 #if defined(TARGET_PPC64)
1508 gen_op_andi_T0(MASK(mb, me));
1510 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1511 if (unlikely(Rc(ctx->opcode) != 0))
1515 #if defined(TARGET_PPC64)
1516 #define GEN_PPC64_R2(name, opc1, opc2) \
1517 GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1519 gen_##name(ctx, 0); \
1521 GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1524 gen_##name(ctx, 1); \
1526 #define GEN_PPC64_R4(name, opc1, opc2) \
1527 GEN_HANDLER2(name##0, stringify(name), opc1, opc2, 0xFF, 0x00000000, PPC_64B) \
1529 gen_##name(ctx, 0, 0); \
1531 GEN_HANDLER2(name##1, stringify(name), opc1, opc2 | 0x01, 0xFF, 0x00000000, \
1534 gen_##name(ctx, 0, 1); \
1536 GEN_HANDLER2(name##2, stringify(name), opc1, opc2 | 0x10, 0xFF, 0x00000000, \
1539 gen_##name(ctx, 1, 0); \
1541 GEN_HANDLER2(name##3, stringify(name), opc1, opc2 | 0x11, 0xFF, 0x00000000, \
1544 gen_##name(ctx, 1, 1); \
1547 static always_inline void gen_andi_T0_64 (DisasContext *ctx, uint64_t mask)
1550 gen_op_andi_T0_64(mask >> 32, mask & 0xFFFFFFFF);
1552 gen_op_andi_T0(mask);
1555 static always_inline void gen_andi_T1_64 (DisasContext *ctx, uint64_t mask)
1558 gen_op_andi_T1_64(mask >> 32, mask & 0xFFFFFFFF);
1560 gen_op_andi_T1(mask);
1563 static always_inline void gen_rldinm (DisasContext *ctx, uint32_t mb,
1564 uint32_t me, uint32_t sh)
1566 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1567 if (likely(sh == 0)) {
1570 if (likely(mb == 0)) {
1571 if (likely(me == 63)) {
1572 gen_op_rotli64_T0(sh);
1574 } else if (likely(me == (63 - sh))) {
1578 } else if (likely(me == 63)) {
1579 if (likely(sh == (64 - mb))) {
1580 gen_op_srli_T0_64(mb);
1584 gen_op_rotli64_T0(sh);
1586 gen_andi_T0_64(ctx, MASK(mb, me));
1588 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1589 if (unlikely(Rc(ctx->opcode) != 0))
1592 /* rldicl - rldicl. */
1593 static always_inline void gen_rldicl (DisasContext *ctx, int mbn, int shn)
1597 sh = SH(ctx->opcode) | (shn << 5);
1598 mb = MB(ctx->opcode) | (mbn << 5);
1599 gen_rldinm(ctx, mb, 63, sh);
1601 GEN_PPC64_R4(rldicl, 0x1E, 0x00);
1602 /* rldicr - rldicr. */
1603 static always_inline void gen_rldicr (DisasContext *ctx, int men, int shn)
1607 sh = SH(ctx->opcode) | (shn << 5);
1608 me = MB(ctx->opcode) | (men << 5);
1609 gen_rldinm(ctx, 0, me, sh);
1611 GEN_PPC64_R4(rldicr, 0x1E, 0x02);
1612 /* rldic - rldic. */
1613 static always_inline void gen_rldic (DisasContext *ctx, int mbn, int shn)
1617 sh = SH(ctx->opcode) | (shn << 5);
1618 mb = MB(ctx->opcode) | (mbn << 5);
1619 gen_rldinm(ctx, mb, 63 - sh, sh);
1621 GEN_PPC64_R4(rldic, 0x1E, 0x04);
1623 static always_inline void gen_rldnm (DisasContext *ctx, uint32_t mb,
1626 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1627 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
1628 gen_op_rotl64_T0_T1();
1629 if (unlikely(mb != 0 || me != 63)) {
1630 gen_andi_T0_64(ctx, MASK(mb, me));
1632 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1633 if (unlikely(Rc(ctx->opcode) != 0))
1637 /* rldcl - rldcl. */
1638 static always_inline void gen_rldcl (DisasContext *ctx, int mbn)
1642 mb = MB(ctx->opcode) | (mbn << 5);
1643 gen_rldnm(ctx, mb, 63);
1645 GEN_PPC64_R2(rldcl, 0x1E, 0x08);
1646 /* rldcr - rldcr. */
1647 static always_inline void gen_rldcr (DisasContext *ctx, int men)
1651 me = MB(ctx->opcode) | (men << 5);
1652 gen_rldnm(ctx, 0, me);
1654 GEN_PPC64_R2(rldcr, 0x1E, 0x09);
1655 /* rldimi - rldimi. */
1656 static always_inline void gen_rldimi (DisasContext *ctx, int mbn, int shn)
1659 uint32_t sh, mb, me;
1661 sh = SH(ctx->opcode) | (shn << 5);
1662 mb = MB(ctx->opcode) | (mbn << 5);
1664 if (likely(sh == 0)) {
1665 if (likely(mb == 0)) {
1666 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1669 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1670 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1673 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1674 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
1675 gen_op_rotli64_T0(sh);
1677 mask = MASK(mb, me);
1678 gen_andi_T0_64(ctx, mask);
1679 gen_andi_T1_64(ctx, ~mask);
1682 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1683 if (unlikely(Rc(ctx->opcode) != 0))
1686 GEN_PPC64_R4(rldimi, 0x1E, 0x06);
1689 /*** Integer shift ***/
1691 __GEN_LOGICAL2(slw, 0x18, 0x00, PPC_INTEGER);
1693 __GEN_LOGICAL2(sraw, 0x18, 0x18, PPC_INTEGER);
1694 /* srawi & srawi. */
1695 GEN_HANDLER(srawi, 0x1F, 0x18, 0x19, 0x00000000, PPC_INTEGER)
1698 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1699 if (SH(ctx->opcode) != 0) {
1700 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1701 mb = 32 - SH(ctx->opcode);
1703 #if defined(TARGET_PPC64)
1707 gen_op_srawi(SH(ctx->opcode), MASK(mb, me));
1709 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1710 if (unlikely(Rc(ctx->opcode) != 0))
1714 __GEN_LOGICAL2(srw, 0x18, 0x10, PPC_INTEGER);
1716 #if defined(TARGET_PPC64)
1718 __GEN_LOGICAL2(sld, 0x1B, 0x00, PPC_64B);
1720 __GEN_LOGICAL2(srad, 0x1A, 0x18, PPC_64B);
1721 /* sradi & sradi. */
1722 static always_inline void gen_sradi (DisasContext *ctx, int n)
1727 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
1728 sh = SH(ctx->opcode) + (n << 5);
1730 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
1731 mb = 64 - SH(ctx->opcode);
1733 mask = MASK(mb, me);
1734 gen_op_sradi(sh, mask >> 32, mask);
1736 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
1737 if (unlikely(Rc(ctx->opcode) != 0))
1740 GEN_HANDLER2(sradi0, "sradi", 0x1F, 0x1A, 0x19, 0x00000000, PPC_64B)
1744 GEN_HANDLER2(sradi1, "sradi", 0x1F, 0x1B, 0x19, 0x00000000, PPC_64B)
1749 __GEN_LOGICAL2(srd, 0x1B, 0x10, PPC_64B);
1752 /*** Floating-Point arithmetic ***/
1753 #define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
1754 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x00000000, type) \
1756 if (unlikely(!ctx->fpu_enabled)) { \
1757 GEN_EXCP_NO_FP(ctx); \
1760 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1761 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1762 gen_op_load_fpr_FT2(rB(ctx->opcode)); \
1763 gen_reset_fpstatus(); \
1768 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1769 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1772 #define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
1773 _GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
1774 _GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
1776 #define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1777 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1779 if (unlikely(!ctx->fpu_enabled)) { \
1780 GEN_EXCP_NO_FP(ctx); \
1783 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1784 gen_op_load_fpr_FT1(rB(ctx->opcode)); \
1785 gen_reset_fpstatus(); \
1790 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1791 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1793 #define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
1794 _GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1795 _GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1797 #define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
1798 GEN_HANDLER(f##name, op1, op2, 0xFF, inval, type) \
1800 if (unlikely(!ctx->fpu_enabled)) { \
1801 GEN_EXCP_NO_FP(ctx); \
1804 gen_op_load_fpr_FT0(rA(ctx->opcode)); \
1805 gen_op_load_fpr_FT1(rC(ctx->opcode)); \
1806 gen_reset_fpstatus(); \
1811 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1812 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1814 #define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
1815 _GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
1816 _GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
1818 #define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
1819 GEN_HANDLER(f##name, 0x3F, op2, op3, 0x001F0000, type) \
1821 if (unlikely(!ctx->fpu_enabled)) { \
1822 GEN_EXCP_NO_FP(ctx); \
1825 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1826 gen_reset_fpstatus(); \
1828 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1829 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1832 #define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
1833 GEN_HANDLER(f##name, op1, op2, 0xFF, 0x001F07C0, type) \
1835 if (unlikely(!ctx->fpu_enabled)) { \
1836 GEN_EXCP_NO_FP(ctx); \
1839 gen_op_load_fpr_FT0(rB(ctx->opcode)); \
1840 gen_reset_fpstatus(); \
1842 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
1843 gen_compute_fprf(set_fprf, Rc(ctx->opcode) != 0); \
1847 GEN_FLOAT_AB(add, 0x15, 0x000007C0, 1, PPC_FLOAT);
1849 GEN_FLOAT_AB(div, 0x12, 0x000007C0, 1, PPC_FLOAT);
1851 GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT);
1854 GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT);
1857 GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES);
1860 GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE);
1863 static always_inline void gen_op_frsqrtes (void)
1868 GEN_FLOAT_BS(rsqrtes, 0x3B, 0x1A, 1, PPC_FLOAT_FRSQRTES);
1871 _GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
1873 GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
1876 GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1878 if (unlikely(!ctx->fpu_enabled)) {
1879 GEN_EXCP_NO_FP(ctx);
1882 gen_op_load_fpr_FT0(rB(ctx->opcode));
1883 gen_reset_fpstatus();
1885 gen_op_store_FT0_fpr(rD(ctx->opcode));
1886 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1889 GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT)
1891 if (unlikely(!ctx->fpu_enabled)) {
1892 GEN_EXCP_NO_FP(ctx);
1895 gen_op_load_fpr_FT0(rB(ctx->opcode));
1896 gen_reset_fpstatus();
1899 gen_op_store_FT0_fpr(rD(ctx->opcode));
1900 gen_compute_fprf(1, Rc(ctx->opcode) != 0);
1903 /*** Floating-Point multiply-and-add ***/
1904 /* fmadd - fmadds */
1905 GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
1906 /* fmsub - fmsubs */
1907 GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT);
1908 /* fnmadd - fnmadds */
1909 GEN_FLOAT_ACB(nmadd, 0x1F, 1, PPC_FLOAT);
1910 /* fnmsub - fnmsubs */
1911 GEN_FLOAT_ACB(nmsub, 0x1E, 1, PPC_FLOAT);
1913 /*** Floating-Point round & convert ***/
1915 GEN_FLOAT_B(ctiw, 0x0E, 0x00, 0, PPC_FLOAT);
1917 GEN_FLOAT_B(ctiwz, 0x0F, 0x00, 0, PPC_FLOAT);
1919 GEN_FLOAT_B(rsp, 0x0C, 0x00, 1, PPC_FLOAT);
1920 #if defined(TARGET_PPC64)
1922 GEN_FLOAT_B(cfid, 0x0E, 0x1A, 1, PPC_64B);
1924 GEN_FLOAT_B(ctid, 0x0E, 0x19, 0, PPC_64B);
1926 GEN_FLOAT_B(ctidz, 0x0F, 0x19, 0, PPC_64B);
1930 GEN_FLOAT_B(rin, 0x08, 0x0C, 1, PPC_FLOAT_EXT);
1932 GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT);
1934 GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT);
1936 GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT);
1938 /*** Floating-Point compare ***/
1940 GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT)
1942 if (unlikely(!ctx->fpu_enabled)) {
1943 GEN_EXCP_NO_FP(ctx);
1946 gen_op_load_fpr_FT0(rA(ctx->opcode));
1947 gen_op_load_fpr_FT1(rB(ctx->opcode));
1948 gen_reset_fpstatus();
1950 gen_op_store_T0_crf(crfD(ctx->opcode));
1951 gen_op_float_check_status();
1955 GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT)
1957 if (unlikely(!ctx->fpu_enabled)) {
1958 GEN_EXCP_NO_FP(ctx);
1961 gen_op_load_fpr_FT0(rA(ctx->opcode));
1962 gen_op_load_fpr_FT1(rB(ctx->opcode));
1963 gen_reset_fpstatus();
1965 gen_op_store_T0_crf(crfD(ctx->opcode));
1966 gen_op_float_check_status();
1969 /*** Floating-point move ***/
1971 /* XXX: beware that fabs never checks for NaNs nor update FPSCR */
1972 GEN_FLOAT_B(abs, 0x08, 0x08, 0, PPC_FLOAT);
1975 /* XXX: beware that fmr never checks for NaNs nor update FPSCR */
1976 GEN_HANDLER(fmr, 0x3F, 0x08, 0x02, 0x001F0000, PPC_FLOAT)
1978 if (unlikely(!ctx->fpu_enabled)) {
1979 GEN_EXCP_NO_FP(ctx);
1982 gen_op_load_fpr_FT0(rB(ctx->opcode));
1983 gen_op_store_FT0_fpr(rD(ctx->opcode));
1984 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
1988 /* XXX: beware that fnabs never checks for NaNs nor update FPSCR */
1989 GEN_FLOAT_B(nabs, 0x08, 0x04, 0, PPC_FLOAT);
1991 /* XXX: beware that fneg never checks for NaNs nor update FPSCR */
1992 GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT);
1994 /*** Floating-Point status & ctrl register ***/
1996 GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT)
2000 if (unlikely(!ctx->fpu_enabled)) {
2001 GEN_EXCP_NO_FP(ctx);
2004 gen_optimize_fprf();
2005 bfa = 4 * (7 - crfS(ctx->opcode));
2006 gen_op_load_fpscr_T0(bfa);
2007 gen_op_store_T0_crf(crfD(ctx->opcode));
2008 gen_op_fpscr_resetbit(~(0xF << bfa));
2012 GEN_HANDLER(mffs, 0x3F, 0x07, 0x12, 0x001FF800, PPC_FLOAT)
2014 if (unlikely(!ctx->fpu_enabled)) {
2015 GEN_EXCP_NO_FP(ctx);
2018 gen_optimize_fprf();
2019 gen_reset_fpstatus();
2020 gen_op_load_fpscr_FT0();
2021 gen_op_store_FT0_fpr(rD(ctx->opcode));
2022 gen_compute_fprf(0, Rc(ctx->opcode) != 0);
2026 GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT)
2030 if (unlikely(!ctx->fpu_enabled)) {
2031 GEN_EXCP_NO_FP(ctx);
2034 crb = 32 - (crbD(ctx->opcode) >> 2);
2035 gen_optimize_fprf();
2036 gen_reset_fpstatus();
2037 if (likely(crb != 30 && crb != 29))
2038 gen_op_fpscr_resetbit(~(1 << crb));
2039 if (unlikely(Rc(ctx->opcode) != 0)) {
2046 GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT)
2050 if (unlikely(!ctx->fpu_enabled)) {
2051 GEN_EXCP_NO_FP(ctx);
2054 crb = 32 - (crbD(ctx->opcode) >> 2);
2055 gen_optimize_fprf();
2056 gen_reset_fpstatus();
2057 /* XXX: we pretend we can only do IEEE floating-point computations */
2058 if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI))
2059 gen_op_fpscr_setbit(crb);
2060 if (unlikely(Rc(ctx->opcode) != 0)) {
2064 /* We can raise a differed exception */
2065 gen_op_float_check_status();
2069 GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
2071 if (unlikely(!ctx->fpu_enabled)) {
2072 GEN_EXCP_NO_FP(ctx);
2075 gen_optimize_fprf();
2076 gen_op_load_fpr_FT0(rB(ctx->opcode));
2077 gen_reset_fpstatus();
2078 gen_op_store_fpscr(FM(ctx->opcode));
2079 if (unlikely(Rc(ctx->opcode) != 0)) {
2083 /* We can raise a differed exception */
2084 gen_op_float_check_status();
2088 GEN_HANDLER(mtfsfi, 0x3F, 0x06, 0x04, 0x006f0800, PPC_FLOAT)
2092 if (unlikely(!ctx->fpu_enabled)) {
2093 GEN_EXCP_NO_FP(ctx);
2096 bf = crbD(ctx->opcode) >> 2;
2098 gen_optimize_fprf();
2099 gen_op_set_FT0(FPIMM(ctx->opcode) << (4 * sh));
2100 gen_reset_fpstatus();
2101 gen_op_store_fpscr(1 << sh);
2102 if (unlikely(Rc(ctx->opcode) != 0)) {
2106 /* We can raise a differed exception */
2107 gen_op_float_check_status();
2110 /*** Addressing modes ***/
2111 /* Register indirect with immediate index : EA = (rA|0) + SIMM */
2112 static always_inline void gen_addr_imm_index (DisasContext *ctx,
2115 target_long simm = SIMM(ctx->opcode);
2118 if (rA(ctx->opcode) == 0) {
2119 tcg_gen_movi_tl(cpu_T[0], simm);
2121 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2122 if (likely(simm != 0))
2125 #ifdef DEBUG_MEMORY_ACCESSES
2126 gen_op_print_mem_EA();
2130 static always_inline void gen_addr_reg_index (DisasContext *ctx)
2132 if (rA(ctx->opcode) == 0) {
2133 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
2135 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2136 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
2139 #ifdef DEBUG_MEMORY_ACCESSES
2140 gen_op_print_mem_EA();
2144 static always_inline void gen_addr_register (DisasContext *ctx)
2146 if (rA(ctx->opcode) == 0) {
2147 tcg_gen_movi_tl(cpu_T[0], 0);
2149 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
2151 #ifdef DEBUG_MEMORY_ACCESSES
2152 gen_op_print_mem_EA();
2156 #if defined(TARGET_PPC64)
2157 #define _GEN_MEM_FUNCS(name, mode) \
2158 &gen_op_##name##_##mode, \
2159 &gen_op_##name##_le_##mode, \
2160 &gen_op_##name##_64_##mode, \
2161 &gen_op_##name##_le_64_##mode
2163 #define _GEN_MEM_FUNCS(name, mode) \
2164 &gen_op_##name##_##mode, \
2165 &gen_op_##name##_le_##mode
2167 #if defined(CONFIG_USER_ONLY)
2168 #if defined(TARGET_PPC64)
2169 #define NB_MEM_FUNCS 4
2171 #define NB_MEM_FUNCS 2
2173 #define GEN_MEM_FUNCS(name) \
2174 _GEN_MEM_FUNCS(name, raw)
2176 #if defined(TARGET_PPC64)
2177 #define NB_MEM_FUNCS 12
2179 #define NB_MEM_FUNCS 6
2181 #define GEN_MEM_FUNCS(name) \
2182 _GEN_MEM_FUNCS(name, user), \
2183 _GEN_MEM_FUNCS(name, kernel), \
2184 _GEN_MEM_FUNCS(name, hypv)
2187 /*** Integer load ***/
2188 #define op_ldst(name) (*gen_op_##name[ctx->mem_idx])()
2189 /* Byte access routine are endian safe */
2190 #define gen_op_lbz_le_raw gen_op_lbz_raw
2191 #define gen_op_lbz_le_user gen_op_lbz_user
2192 #define gen_op_lbz_le_kernel gen_op_lbz_kernel
2193 #define gen_op_lbz_le_hypv gen_op_lbz_hypv
2194 #define gen_op_lbz_le_64_raw gen_op_lbz_64_raw
2195 #define gen_op_lbz_le_64_user gen_op_lbz_64_user
2196 #define gen_op_lbz_le_64_kernel gen_op_lbz_64_kernel
2197 #define gen_op_lbz_le_64_hypv gen_op_lbz_64_hypv
2198 #define gen_op_stb_le_raw gen_op_stb_raw
2199 #define gen_op_stb_le_user gen_op_stb_user
2200 #define gen_op_stb_le_kernel gen_op_stb_kernel
2201 #define gen_op_stb_le_hypv gen_op_stb_hypv
2202 #define gen_op_stb_le_64_raw gen_op_stb_64_raw
2203 #define gen_op_stb_le_64_user gen_op_stb_64_user
2204 #define gen_op_stb_le_64_kernel gen_op_stb_64_kernel
2205 #define gen_op_stb_le_64_hypv gen_op_stb_64_hypv
2206 #define OP_LD_TABLE(width) \
2207 static GenOpFunc *gen_op_l##width[NB_MEM_FUNCS] = { \
2208 GEN_MEM_FUNCS(l##width), \
2210 #define OP_ST_TABLE(width) \
2211 static GenOpFunc *gen_op_st##width[NB_MEM_FUNCS] = { \
2212 GEN_MEM_FUNCS(st##width), \
2215 #define GEN_LD(width, opc, type) \
2216 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2218 gen_addr_imm_index(ctx, 0); \
2219 op_ldst(l##width); \
2220 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2223 #define GEN_LDU(width, opc, type) \
2224 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2226 if (unlikely(rA(ctx->opcode) == 0 || \
2227 rA(ctx->opcode) == rD(ctx->opcode))) { \
2228 GEN_EXCP_INVAL(ctx); \
2231 if (type == PPC_64B) \
2232 gen_addr_imm_index(ctx, 0x03); \
2234 gen_addr_imm_index(ctx, 0); \
2235 op_ldst(l##width); \
2236 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2237 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2240 #define GEN_LDUX(width, opc2, opc3, type) \
2241 GEN_HANDLER(l##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2243 if (unlikely(rA(ctx->opcode) == 0 || \
2244 rA(ctx->opcode) == rD(ctx->opcode))) { \
2245 GEN_EXCP_INVAL(ctx); \
2248 gen_addr_reg_index(ctx); \
2249 op_ldst(l##width); \
2250 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2251 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2254 #define GEN_LDX(width, opc2, opc3, type) \
2255 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2257 gen_addr_reg_index(ctx); \
2258 op_ldst(l##width); \
2259 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]); \
2262 #define GEN_LDS(width, op, type) \
2263 OP_LD_TABLE(width); \
2264 GEN_LD(width, op | 0x20, type); \
2265 GEN_LDU(width, op | 0x21, type); \
2266 GEN_LDUX(width, 0x17, op | 0x01, type); \
2267 GEN_LDX(width, 0x17, op | 0x00, type)
2269 /* lbz lbzu lbzux lbzx */
2270 GEN_LDS(bz, 0x02, PPC_INTEGER);
2271 /* lha lhau lhaux lhax */
2272 GEN_LDS(ha, 0x0A, PPC_INTEGER);
2273 /* lhz lhzu lhzux lhzx */
2274 GEN_LDS(hz, 0x08, PPC_INTEGER);
2275 /* lwz lwzu lwzux lwzx */
2276 GEN_LDS(wz, 0x00, PPC_INTEGER);
2277 #if defined(TARGET_PPC64)
2281 GEN_LDUX(wa, 0x15, 0x0B, PPC_64B);
2283 GEN_LDX(wa, 0x15, 0x0A, PPC_64B);
2285 GEN_LDUX(d, 0x15, 0x01, PPC_64B);
2287 GEN_LDX(d, 0x15, 0x00, PPC_64B);
2288 GEN_HANDLER(ld, 0x3A, 0xFF, 0xFF, 0x00000000, PPC_64B)
2290 if (Rc(ctx->opcode)) {
2291 if (unlikely(rA(ctx->opcode) == 0 ||
2292 rA(ctx->opcode) == rD(ctx->opcode))) {
2293 GEN_EXCP_INVAL(ctx);
2297 gen_addr_imm_index(ctx, 0x03);
2298 if (ctx->opcode & 0x02) {
2299 /* lwa (lwau is undefined) */
2305 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2306 if (Rc(ctx->opcode))
2307 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2310 GEN_HANDLER(lq, 0x38, 0xFF, 0xFF, 0x00000000, PPC_64BX)
2312 #if defined(CONFIG_USER_ONLY)
2313 GEN_EXCP_PRIVOPC(ctx);
2317 /* Restore CPU state */
2318 if (unlikely(ctx->supervisor == 0)) {
2319 GEN_EXCP_PRIVOPC(ctx);
2322 ra = rA(ctx->opcode);
2323 rd = rD(ctx->opcode);
2324 if (unlikely((rd & 1) || rd == ra)) {
2325 GEN_EXCP_INVAL(ctx);
2328 if (unlikely(ctx->mem_idx & 1)) {
2329 /* Little-endian mode is not handled */
2330 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2333 gen_addr_imm_index(ctx, 0x0F);
2335 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[1]);
2338 tcg_gen_mov_tl(cpu_gpr[rd + 1], cpu_T[1]);
2343 /*** Integer store ***/
2344 #define GEN_ST(width, opc, type) \
2345 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2347 gen_addr_imm_index(ctx, 0); \
2348 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2349 op_ldst(st##width); \
2352 #define GEN_STU(width, opc, type) \
2353 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2355 if (unlikely(rA(ctx->opcode) == 0)) { \
2356 GEN_EXCP_INVAL(ctx); \
2359 if (type == PPC_64B) \
2360 gen_addr_imm_index(ctx, 0x03); \
2362 gen_addr_imm_index(ctx, 0); \
2363 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2364 op_ldst(st##width); \
2365 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2368 #define GEN_STUX(width, opc2, opc3, type) \
2369 GEN_HANDLER(st##width##ux, 0x1F, opc2, opc3, 0x00000001, type) \
2371 if (unlikely(rA(ctx->opcode) == 0)) { \
2372 GEN_EXCP_INVAL(ctx); \
2375 gen_addr_reg_index(ctx); \
2376 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2377 op_ldst(st##width); \
2378 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2381 #define GEN_STX(width, opc2, opc3, type) \
2382 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2384 gen_addr_reg_index(ctx); \
2385 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]); \
2386 op_ldst(st##width); \
2389 #define GEN_STS(width, op, type) \
2390 OP_ST_TABLE(width); \
2391 GEN_ST(width, op | 0x20, type); \
2392 GEN_STU(width, op | 0x21, type); \
2393 GEN_STUX(width, 0x17, op | 0x01, type); \
2394 GEN_STX(width, 0x17, op | 0x00, type)
2396 /* stb stbu stbux stbx */
2397 GEN_STS(b, 0x06, PPC_INTEGER);
2398 /* sth sthu sthux sthx */
2399 GEN_STS(h, 0x0C, PPC_INTEGER);
2400 /* stw stwu stwux stwx */
2401 GEN_STS(w, 0x04, PPC_INTEGER);
2402 #if defined(TARGET_PPC64)
2404 GEN_STUX(d, 0x15, 0x05, PPC_64B);
2405 GEN_STX(d, 0x15, 0x04, PPC_64B);
2406 GEN_HANDLER(std, 0x3E, 0xFF, 0xFF, 0x00000000, PPC_64B)
2410 rs = rS(ctx->opcode);
2411 if ((ctx->opcode & 0x3) == 0x2) {
2412 #if defined(CONFIG_USER_ONLY)
2413 GEN_EXCP_PRIVOPC(ctx);
2416 if (unlikely(ctx->supervisor == 0)) {
2417 GEN_EXCP_PRIVOPC(ctx);
2420 if (unlikely(rs & 1)) {
2421 GEN_EXCP_INVAL(ctx);
2424 if (unlikely(ctx->mem_idx & 1)) {
2425 /* Little-endian mode is not handled */
2426 GEN_EXCP(ctx, POWERPC_EXCP_ALIGN, POWERPC_EXCP_ALIGN_LE);
2429 gen_addr_imm_index(ctx, 0x03);
2430 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2433 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs + 1]);
2438 if (Rc(ctx->opcode)) {
2439 if (unlikely(rA(ctx->opcode) == 0)) {
2440 GEN_EXCP_INVAL(ctx);
2444 gen_addr_imm_index(ctx, 0x03);
2445 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rs]);
2447 if (Rc(ctx->opcode))
2448 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
2452 /*** Integer load and store with byte reverse ***/
2455 GEN_LDX(hbr, 0x16, 0x18, PPC_INTEGER);
2458 GEN_LDX(wbr, 0x16, 0x10, PPC_INTEGER);
2461 GEN_STX(hbr, 0x16, 0x1C, PPC_INTEGER);
2464 GEN_STX(wbr, 0x16, 0x14, PPC_INTEGER);
2466 /*** Integer load and store multiple ***/
2467 #define op_ldstm(name, reg) (*gen_op_##name[ctx->mem_idx])(reg)
2468 static GenOpFunc1 *gen_op_lmw[NB_MEM_FUNCS] = {
2471 static GenOpFunc1 *gen_op_stmw[NB_MEM_FUNCS] = {
2472 GEN_MEM_FUNCS(stmw),
2476 GEN_HANDLER(lmw, 0x2E, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2478 /* NIP cannot be restored if the memory exception comes from an helper */
2479 gen_update_nip(ctx, ctx->nip - 4);
2480 gen_addr_imm_index(ctx, 0);
2481 op_ldstm(lmw, rD(ctx->opcode));
2485 GEN_HANDLER(stmw, 0x2F, 0xFF, 0xFF, 0x00000000, PPC_INTEGER)
2487 /* NIP cannot be restored if the memory exception comes from an helper */
2488 gen_update_nip(ctx, ctx->nip - 4);
2489 gen_addr_imm_index(ctx, 0);
2490 op_ldstm(stmw, rS(ctx->opcode));
2493 /*** Integer load and store strings ***/
2494 #define op_ldsts(name, start) (*gen_op_##name[ctx->mem_idx])(start)
2495 #define op_ldstsx(name, rd, ra, rb) (*gen_op_##name[ctx->mem_idx])(rd, ra, rb)
2496 /* string load & stores are by definition endian-safe */
2497 #define gen_op_lswi_le_raw gen_op_lswi_raw
2498 #define gen_op_lswi_le_user gen_op_lswi_user
2499 #define gen_op_lswi_le_kernel gen_op_lswi_kernel
2500 #define gen_op_lswi_le_hypv gen_op_lswi_hypv
2501 #define gen_op_lswi_le_64_raw gen_op_lswi_raw
2502 #define gen_op_lswi_le_64_user gen_op_lswi_user
2503 #define gen_op_lswi_le_64_kernel gen_op_lswi_kernel
2504 #define gen_op_lswi_le_64_hypv gen_op_lswi_hypv
2505 static GenOpFunc1 *gen_op_lswi[NB_MEM_FUNCS] = {
2506 GEN_MEM_FUNCS(lswi),
2508 #define gen_op_lswx_le_raw gen_op_lswx_raw
2509 #define gen_op_lswx_le_user gen_op_lswx_user
2510 #define gen_op_lswx_le_kernel gen_op_lswx_kernel
2511 #define gen_op_lswx_le_hypv gen_op_lswx_hypv
2512 #define gen_op_lswx_le_64_raw gen_op_lswx_raw
2513 #define gen_op_lswx_le_64_user gen_op_lswx_user
2514 #define gen_op_lswx_le_64_kernel gen_op_lswx_kernel
2515 #define gen_op_lswx_le_64_hypv gen_op_lswx_hypv
2516 static GenOpFunc3 *gen_op_lswx[NB_MEM_FUNCS] = {
2517 GEN_MEM_FUNCS(lswx),
2519 #define gen_op_stsw_le_raw gen_op_stsw_raw
2520 #define gen_op_stsw_le_user gen_op_stsw_user
2521 #define gen_op_stsw_le_kernel gen_op_stsw_kernel
2522 #define gen_op_stsw_le_hypv gen_op_stsw_hypv
2523 #define gen_op_stsw_le_64_raw gen_op_stsw_raw
2524 #define gen_op_stsw_le_64_user gen_op_stsw_user
2525 #define gen_op_stsw_le_64_kernel gen_op_stsw_kernel
2526 #define gen_op_stsw_le_64_hypv gen_op_stsw_hypv
2527 static GenOpFunc1 *gen_op_stsw[NB_MEM_FUNCS] = {
2528 GEN_MEM_FUNCS(stsw),
2532 /* PowerPC32 specification says we must generate an exception if
2533 * rA is in the range of registers to be loaded.
2534 * In an other hand, IBM says this is valid, but rA won't be loaded.
2535 * For now, I'll follow the spec...
2537 GEN_HANDLER(lswi, 0x1F, 0x15, 0x12, 0x00000001, PPC_STRING)
2539 int nb = NB(ctx->opcode);
2540 int start = rD(ctx->opcode);
2541 int ra = rA(ctx->opcode);
2547 if (unlikely(((start + nr) > 32 &&
2548 start <= ra && (start + nr - 32) > ra) ||
2549 ((start + nr) <= 32 && start <= ra && (start + nr) > ra))) {
2550 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
2551 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_LSWX);
2554 /* NIP cannot be restored if the memory exception comes from an helper */
2555 gen_update_nip(ctx, ctx->nip - 4);
2556 gen_addr_register(ctx);
2557 tcg_gen_movi_tl(cpu_T[1], nb);
2558 op_ldsts(lswi, start);
2562 GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING)
2564 int ra = rA(ctx->opcode);
2565 int rb = rB(ctx->opcode);
2567 /* NIP cannot be restored if the memory exception comes from an helper */
2568 gen_update_nip(ctx, ctx->nip - 4);
2569 gen_addr_reg_index(ctx);
2573 gen_op_load_xer_bc();
2574 op_ldstsx(lswx, rD(ctx->opcode), ra, rb);
2578 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING)
2580 int nb = NB(ctx->opcode);
2582 /* NIP cannot be restored if the memory exception comes from an helper */
2583 gen_update_nip(ctx, ctx->nip - 4);
2584 gen_addr_register(ctx);
2587 tcg_gen_movi_tl(cpu_T[1], nb);
2588 op_ldsts(stsw, rS(ctx->opcode));
2592 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING)
2594 /* NIP cannot be restored if the memory exception comes from an helper */
2595 gen_update_nip(ctx, ctx->nip - 4);
2596 gen_addr_reg_index(ctx);
2597 gen_op_load_xer_bc();
2598 op_ldsts(stsw, rS(ctx->opcode));
2601 /*** Memory synchronisation ***/
2603 GEN_HANDLER(eieio, 0x1F, 0x16, 0x1A, 0x03FFF801, PPC_MEM_EIEIO)
2608 GEN_HANDLER(isync, 0x13, 0x16, 0x04, 0x03FFF801, PPC_MEM)
2613 #define op_lwarx() (*gen_op_lwarx[ctx->mem_idx])()
2614 #define op_stwcx() (*gen_op_stwcx[ctx->mem_idx])()
2615 static GenOpFunc *gen_op_lwarx[NB_MEM_FUNCS] = {
2616 GEN_MEM_FUNCS(lwarx),
2618 static GenOpFunc *gen_op_stwcx[NB_MEM_FUNCS] = {
2619 GEN_MEM_FUNCS(stwcx),
2623 GEN_HANDLER(lwarx, 0x1F, 0x14, 0x00, 0x00000001, PPC_RES)
2625 /* NIP cannot be restored if the memory exception comes from an helper */
2626 gen_update_nip(ctx, ctx->nip - 4);
2627 gen_addr_reg_index(ctx);
2629 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2633 GEN_HANDLER2(stwcx_, "stwcx.", 0x1F, 0x16, 0x04, 0x00000000, PPC_RES)
2635 /* NIP cannot be restored if the memory exception comes from an helper */
2636 gen_update_nip(ctx, ctx->nip - 4);
2637 gen_addr_reg_index(ctx);
2638 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
2642 #if defined(TARGET_PPC64)
2643 #define op_ldarx() (*gen_op_ldarx[ctx->mem_idx])()
2644 #define op_stdcx() (*gen_op_stdcx[ctx->mem_idx])()
2645 static GenOpFunc *gen_op_ldarx[NB_MEM_FUNCS] = {
2646 GEN_MEM_FUNCS(ldarx),
2648 static GenOpFunc *gen_op_stdcx[NB_MEM_FUNCS] = {
2649 GEN_MEM_FUNCS(stdcx),
2653 GEN_HANDLER(ldarx, 0x1F, 0x14, 0x02, 0x00000001, PPC_64B)
2655 /* NIP cannot be restored if the memory exception comes from an helper */
2656 gen_update_nip(ctx, ctx->nip - 4);
2657 gen_addr_reg_index(ctx);
2659 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[1]);
2663 GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 0x00000000, PPC_64B)
2665 /* NIP cannot be restored if the memory exception comes from an helper */
2666 gen_update_nip(ctx, ctx->nip - 4);
2667 gen_addr_reg_index(ctx);
2668 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
2671 #endif /* defined(TARGET_PPC64) */
2674 GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC)
2679 GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT)
2681 /* Stop translation, as the CPU is supposed to sleep from now */
2683 GEN_EXCP(ctx, EXCP_HLT, 1);
2686 /*** Floating-point load ***/
2687 #define GEN_LDF(width, opc, type) \
2688 GEN_HANDLER(l##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2690 if (unlikely(!ctx->fpu_enabled)) { \
2691 GEN_EXCP_NO_FP(ctx); \
2694 gen_addr_imm_index(ctx, 0); \
2695 op_ldst(l##width); \
2696 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2699 #define GEN_LDUF(width, opc, type) \
2700 GEN_HANDLER(l##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2702 if (unlikely(!ctx->fpu_enabled)) { \
2703 GEN_EXCP_NO_FP(ctx); \
2706 if (unlikely(rA(ctx->opcode) == 0)) { \
2707 GEN_EXCP_INVAL(ctx); \
2710 gen_addr_imm_index(ctx, 0); \
2711 op_ldst(l##width); \
2712 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2713 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2716 #define GEN_LDUXF(width, opc, type) \
2717 GEN_HANDLER(l##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
2719 if (unlikely(!ctx->fpu_enabled)) { \
2720 GEN_EXCP_NO_FP(ctx); \
2723 if (unlikely(rA(ctx->opcode) == 0)) { \
2724 GEN_EXCP_INVAL(ctx); \
2727 gen_addr_reg_index(ctx); \
2728 op_ldst(l##width); \
2729 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2730 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2733 #define GEN_LDXF(width, opc2, opc3, type) \
2734 GEN_HANDLER(l##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2736 if (unlikely(!ctx->fpu_enabled)) { \
2737 GEN_EXCP_NO_FP(ctx); \
2740 gen_addr_reg_index(ctx); \
2741 op_ldst(l##width); \
2742 gen_op_store_FT0_fpr(rD(ctx->opcode)); \
2745 #define GEN_LDFS(width, op, type) \
2746 OP_LD_TABLE(width); \
2747 GEN_LDF(width, op | 0x20, type); \
2748 GEN_LDUF(width, op | 0x21, type); \
2749 GEN_LDUXF(width, op | 0x01, type); \
2750 GEN_LDXF(width, 0x17, op | 0x00, type)
2752 /* lfd lfdu lfdux lfdx */
2753 GEN_LDFS(fd, 0x12, PPC_FLOAT);
2754 /* lfs lfsu lfsux lfsx */
2755 GEN_LDFS(fs, 0x10, PPC_FLOAT);
2757 /*** Floating-point store ***/
2758 #define GEN_STF(width, opc, type) \
2759 GEN_HANDLER(st##width, opc, 0xFF, 0xFF, 0x00000000, type) \
2761 if (unlikely(!ctx->fpu_enabled)) { \
2762 GEN_EXCP_NO_FP(ctx); \
2765 gen_addr_imm_index(ctx, 0); \
2766 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2767 op_ldst(st##width); \
2770 #define GEN_STUF(width, opc, type) \
2771 GEN_HANDLER(st##width##u, opc, 0xFF, 0xFF, 0x00000000, type) \
2773 if (unlikely(!ctx->fpu_enabled)) { \
2774 GEN_EXCP_NO_FP(ctx); \
2777 if (unlikely(rA(ctx->opcode) == 0)) { \
2778 GEN_EXCP_INVAL(ctx); \
2781 gen_addr_imm_index(ctx, 0); \
2782 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2783 op_ldst(st##width); \
2784 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2787 #define GEN_STUXF(width, opc, type) \
2788 GEN_HANDLER(st##width##ux, 0x1F, 0x17, opc, 0x00000001, type) \
2790 if (unlikely(!ctx->fpu_enabled)) { \
2791 GEN_EXCP_NO_FP(ctx); \
2794 if (unlikely(rA(ctx->opcode) == 0)) { \
2795 GEN_EXCP_INVAL(ctx); \
2798 gen_addr_reg_index(ctx); \
2799 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2800 op_ldst(st##width); \
2801 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]); \
2804 #define GEN_STXF(width, opc2, opc3, type) \
2805 GEN_HANDLER(st##width##x, 0x1F, opc2, opc3, 0x00000001, type) \
2807 if (unlikely(!ctx->fpu_enabled)) { \
2808 GEN_EXCP_NO_FP(ctx); \
2811 gen_addr_reg_index(ctx); \
2812 gen_op_load_fpr_FT0(rS(ctx->opcode)); \
2813 op_ldst(st##width); \
2816 #define GEN_STFS(width, op, type) \
2817 OP_ST_TABLE(width); \
2818 GEN_STF(width, op | 0x20, type); \
2819 GEN_STUF(width, op | 0x21, type); \
2820 GEN_STUXF(width, op | 0x01, type); \
2821 GEN_STXF(width, 0x17, op | 0x00, type)
2823 /* stfd stfdu stfdux stfdx */
2824 GEN_STFS(fd, 0x16, PPC_FLOAT);
2825 /* stfs stfsu stfsux stfsx */
2826 GEN_STFS(fs, 0x14, PPC_FLOAT);
2831 GEN_STXF(fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
2834 static always_inline void gen_goto_tb (DisasContext *ctx, int n,
2837 TranslationBlock *tb;
2839 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) &&
2840 likely(!ctx->singlestep_enabled)) {
2842 tcg_gen_movi_tl(cpu_T[1], dest);
2843 #if defined(TARGET_PPC64)
2849 tcg_gen_exit_tb((long)tb + n);
2851 tcg_gen_movi_tl(cpu_T[1], dest);
2852 #if defined(TARGET_PPC64)
2858 if (unlikely(ctx->singlestep_enabled)) {
2859 if ((ctx->singlestep_enabled &
2860 (CPU_BRANCH_STEP | CPU_SINGLE_STEP)) &&
2861 ctx->exception == POWERPC_EXCP_BRANCH) {
2862 target_ulong tmp = ctx->nip;
2864 GEN_EXCP(ctx, POWERPC_EXCP_TRACE, 0);
2867 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
2868 gen_update_nip(ctx, dest);
2876 static always_inline void gen_setlr (DisasContext *ctx, target_ulong nip)
2878 #if defined(TARGET_PPC64)
2879 if (ctx->sf_mode != 0 && (nip >> 32))
2880 gen_op_setlr_64(ctx->nip >> 32, ctx->nip);
2883 gen_op_setlr(ctx->nip);
2887 GEN_HANDLER(b, 0x12, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
2889 target_ulong li, target;
2891 ctx->exception = POWERPC_EXCP_BRANCH;
2892 /* sign extend LI */
2893 #if defined(TARGET_PPC64)
2895 li = ((int64_t)LI(ctx->opcode) << 38) >> 38;
2898 li = ((int32_t)LI(ctx->opcode) << 6) >> 6;
2899 if (likely(AA(ctx->opcode) == 0))
2900 target = ctx->nip + li - 4;
2903 #if defined(TARGET_PPC64)
2905 target = (uint32_t)target;
2907 if (LK(ctx->opcode))
2908 gen_setlr(ctx, ctx->nip);
2909 gen_goto_tb(ctx, 0, target);
2916 static always_inline void gen_bcond (DisasContext *ctx, int type)
2918 target_ulong target = 0;
2920 uint32_t bo = BO(ctx->opcode);
2921 uint32_t bi = BI(ctx->opcode);
2924 ctx->exception = POWERPC_EXCP_BRANCH;
2925 if ((bo & 0x4) == 0)
2929 li = (target_long)((int16_t)(BD(ctx->opcode)));
2930 if (likely(AA(ctx->opcode) == 0)) {
2931 target = ctx->nip + li - 4;
2935 #if defined(TARGET_PPC64)
2937 target = (uint32_t)target;
2941 gen_op_movl_T1_ctr();
2945 gen_op_movl_T1_lr();
2948 if (LK(ctx->opcode))
2949 gen_setlr(ctx, ctx->nip);
2951 /* No CR condition */
2954 #if defined(TARGET_PPC64)
2956 gen_op_test_ctr_64();
2962 #if defined(TARGET_PPC64)
2964 gen_op_test_ctrz_64();
2972 if (type == BCOND_IM) {
2973 gen_goto_tb(ctx, 0, target);
2976 #if defined(TARGET_PPC64)
2987 mask = 1 << (3 - (bi & 0x03));
2988 gen_op_load_crf_T0(bi >> 2);
2992 #if defined(TARGET_PPC64)
2994 gen_op_test_ctr_true_64(mask);
2997 gen_op_test_ctr_true(mask);
3000 #if defined(TARGET_PPC64)
3002 gen_op_test_ctrz_true_64(mask);
3005 gen_op_test_ctrz_true(mask);
3010 gen_op_test_true(mask);
3016 #if defined(TARGET_PPC64)
3018 gen_op_test_ctr_false_64(mask);
3021 gen_op_test_ctr_false(mask);
3024 #if defined(TARGET_PPC64)
3026 gen_op_test_ctrz_false_64(mask);
3029 gen_op_test_ctrz_false(mask);
3034 gen_op_test_false(mask);
3039 if (type == BCOND_IM) {
3040 int l1 = gen_new_label();
3042 gen_goto_tb(ctx, 0, target);
3044 gen_goto_tb(ctx, 1, ctx->nip);
3046 #if defined(TARGET_PPC64)
3048 gen_op_btest_T1_64(ctx->nip >> 32, ctx->nip);
3051 gen_op_btest_T1(ctx->nip);
3053 if (ctx->singlestep_enabled & GDBSTUB_SINGLE_STEP) {
3054 gen_update_nip(ctx, ctx->nip);
3061 GEN_HANDLER(bc, 0x10, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3063 gen_bcond(ctx, BCOND_IM);
3066 GEN_HANDLER(bcctr, 0x13, 0x10, 0x10, 0x00000000, PPC_FLOW)
3068 gen_bcond(ctx, BCOND_CTR);
3071 GEN_HANDLER(bclr, 0x13, 0x10, 0x00, 0x00000000, PPC_FLOW)
3073 gen_bcond(ctx, BCOND_LR);
3076 /*** Condition register logical ***/
3077 #define GEN_CRLOGIC(op, opc) \
3078 GEN_HANDLER(cr##op, 0x13, 0x01, opc, 0x00000001, PPC_INTEGER) \
3082 gen_op_load_crf_T0(crbA(ctx->opcode) >> 2); \
3083 sh = (crbD(ctx->opcode) & 0x03) - (crbA(ctx->opcode) & 0x03); \
3085 gen_op_srli_T0(sh); \
3087 gen_op_sli_T0(-sh); \
3088 gen_op_load_crf_T1(crbB(ctx->opcode) >> 2); \
3089 sh = (crbD(ctx->opcode) & 0x03) - (crbB(ctx->opcode) & 0x03); \
3091 gen_op_srli_T1(sh); \
3093 gen_op_sli_T1(-sh); \
3095 bitmask = 1 << (3 - (crbD(ctx->opcode) & 0x03)); \
3096 gen_op_andi_T0(bitmask); \
3097 gen_op_load_crf_T1(crbD(ctx->opcode) >> 2); \
3098 gen_op_andi_T1(~bitmask); \
3100 gen_op_store_T0_crf(crbD(ctx->opcode) >> 2); \
3104 GEN_CRLOGIC(and, 0x08);
3106 GEN_CRLOGIC(andc, 0x04);
3108 GEN_CRLOGIC(eqv, 0x09);
3110 GEN_CRLOGIC(nand, 0x07);
3112 GEN_CRLOGIC(nor, 0x01);
3114 GEN_CRLOGIC(or, 0x0E);
3116 GEN_CRLOGIC(orc, 0x0D);
3118 GEN_CRLOGIC(xor, 0x06);
3120 GEN_HANDLER(mcrf, 0x13, 0x00, 0xFF, 0x00000001, PPC_INTEGER)
3122 gen_op_load_crf_T0(crfS(ctx->opcode));
3123 gen_op_store_T0_crf(crfD(ctx->opcode));
3126 /*** System linkage ***/
3127 /* rfi (supervisor only) */
3128 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW)
3130 #if defined(CONFIG_USER_ONLY)
3131 GEN_EXCP_PRIVOPC(ctx);
3133 /* Restore CPU state */
3134 if (unlikely(!ctx->supervisor)) {
3135 GEN_EXCP_PRIVOPC(ctx);
3143 #if defined(TARGET_PPC64)
3144 GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B)
3146 #if defined(CONFIG_USER_ONLY)
3147 GEN_EXCP_PRIVOPC(ctx);
3149 /* Restore CPU state */
3150 if (unlikely(!ctx->supervisor)) {
3151 GEN_EXCP_PRIVOPC(ctx);
3159 GEN_HANDLER(hrfid, 0x13, 0x12, 0x08, 0x03FF8001, PPC_64H)
3161 #if defined(CONFIG_USER_ONLY)
3162 GEN_EXCP_PRIVOPC(ctx);
3164 /* Restore CPU state */
3165 if (unlikely(ctx->supervisor <= 1)) {
3166 GEN_EXCP_PRIVOPC(ctx);
3176 #if defined(CONFIG_USER_ONLY)
3177 #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL_USER
3179 #define POWERPC_SYSCALL POWERPC_EXCP_SYSCALL
3181 GEN_HANDLER(sc, 0x11, 0xFF, 0xFF, 0x03FFF01D, PPC_FLOW)
3185 lev = (ctx->opcode >> 5) & 0x7F;
3186 GEN_EXCP(ctx, POWERPC_SYSCALL, lev);
3191 GEN_HANDLER(tw, 0x1F, 0x04, 0x00, 0x00000001, PPC_FLOW)
3193 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3194 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3195 /* Update the nip since this might generate a trap exception */
3196 gen_update_nip(ctx, ctx->nip);
3197 gen_op_tw(TO(ctx->opcode));
3201 GEN_HANDLER(twi, 0x03, 0xFF, 0xFF, 0x00000000, PPC_FLOW)
3203 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3204 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3205 /* Update the nip since this might generate a trap exception */
3206 gen_update_nip(ctx, ctx->nip);
3207 gen_op_tw(TO(ctx->opcode));
3210 #if defined(TARGET_PPC64)
3212 GEN_HANDLER(td, 0x1F, 0x04, 0x02, 0x00000001, PPC_64B)
3214 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3215 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3216 /* Update the nip since this might generate a trap exception */
3217 gen_update_nip(ctx, ctx->nip);
3218 gen_op_td(TO(ctx->opcode));
3222 GEN_HANDLER(tdi, 0x02, 0xFF, 0xFF, 0x00000000, PPC_64B)
3224 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3225 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3226 /* Update the nip since this might generate a trap exception */
3227 gen_update_nip(ctx, ctx->nip);
3228 gen_op_td(TO(ctx->opcode));
3232 /*** Processor control ***/
3234 GEN_HANDLER(mcrxr, 0x1F, 0x00, 0x10, 0x007FF801, PPC_MISC)
3236 gen_op_load_xer_cr();
3237 gen_op_store_T0_crf(crfD(ctx->opcode));
3238 gen_op_clear_xer_ov();
3239 gen_op_clear_xer_ca();
3243 GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
3247 if (likely(ctx->opcode & 0x00100000)) {
3248 crm = CRM(ctx->opcode);
3249 if (likely((crm ^ (crm - 1)) == 0)) {
3251 gen_op_load_cro(7 - crn);
3256 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3260 GEN_HANDLER(mfmsr, 0x1F, 0x13, 0x02, 0x001FF801, PPC_MISC)
3262 #if defined(CONFIG_USER_ONLY)
3263 GEN_EXCP_PRIVREG(ctx);
3265 if (unlikely(!ctx->supervisor)) {
3266 GEN_EXCP_PRIVREG(ctx);
3270 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3275 #define SPR_NOACCESS ((void *)(-1UL))
3277 static void spr_noaccess (void *opaque, int sprn)
3279 sprn = ((sprn >> 5) & 0x1F) | ((sprn & 0x1F) << 5);
3280 printf("ERROR: try to access SPR %d !\n", sprn);
3282 #define SPR_NOACCESS (&spr_noaccess)
3286 static always_inline void gen_op_mfspr (DisasContext *ctx)
3288 void (*read_cb)(void *opaque, int sprn);
3289 uint32_t sprn = SPR(ctx->opcode);
3291 #if !defined(CONFIG_USER_ONLY)
3292 if (ctx->supervisor == 2)
3293 read_cb = ctx->spr_cb[sprn].hea_read;
3294 else if (ctx->supervisor)
3295 read_cb = ctx->spr_cb[sprn].oea_read;
3298 read_cb = ctx->spr_cb[sprn].uea_read;
3299 if (likely(read_cb != NULL)) {
3300 if (likely(read_cb != SPR_NOACCESS)) {
3301 (*read_cb)(ctx, sprn);
3302 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3304 /* Privilege exception */
3305 /* This is a hack to avoid warnings when running Linux:
3306 * this OS breaks the PowerPC virtualisation model,
3307 * allowing userland application to read the PVR
3309 if (sprn != SPR_PVR) {
3310 if (loglevel != 0) {
3311 fprintf(logfile, "Trying to read privileged spr %d %03x at "
3312 ADDRX "\n", sprn, sprn, ctx->nip);
3314 printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
3315 sprn, sprn, ctx->nip);
3317 GEN_EXCP_PRIVREG(ctx);
3321 if (loglevel != 0) {
3322 fprintf(logfile, "Trying to read invalid spr %d %03x at "
3323 ADDRX "\n", sprn, sprn, ctx->nip);
3325 printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
3326 sprn, sprn, ctx->nip);
3327 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3328 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3332 GEN_HANDLER(mfspr, 0x1F, 0x13, 0x0A, 0x00000001, PPC_MISC)
3338 GEN_HANDLER(mftb, 0x1F, 0x13, 0x0B, 0x00000001, PPC_MFTB)
3344 GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
3348 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3349 crm = CRM(ctx->opcode);
3350 if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
3352 gen_op_srli_T0(crn * 4);
3353 gen_op_andi_T0(0xF);
3354 gen_op_store_cro(7 - crn);
3356 gen_op_store_cr(crm);
3361 #if defined(TARGET_PPC64)
3362 GEN_HANDLER(mtmsrd, 0x1F, 0x12, 0x05, 0x001EF801, PPC_64B)
3364 #if defined(CONFIG_USER_ONLY)
3365 GEN_EXCP_PRIVREG(ctx);
3367 if (unlikely(!ctx->supervisor)) {
3368 GEN_EXCP_PRIVREG(ctx);
3371 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3372 if (ctx->opcode & 0x00010000) {
3373 /* Special form that does not need any synchronisation */
3374 gen_op_update_riee();
3376 /* XXX: we need to update nip before the store
3377 * if we enter power saving mode, we will exit the loop
3378 * directly from ppc_store_msr
3380 gen_update_nip(ctx, ctx->nip);
3382 /* Must stop the translation as machine state (may have) changed */
3383 /* Note that mtmsr is not always defined as context-synchronizing */
3384 ctx->exception = POWERPC_EXCP_STOP;
3390 GEN_HANDLER(mtmsr, 0x1F, 0x12, 0x04, 0x001FF801, PPC_MISC)
3392 #if defined(CONFIG_USER_ONLY)
3393 GEN_EXCP_PRIVREG(ctx);
3395 if (unlikely(!ctx->supervisor)) {
3396 GEN_EXCP_PRIVREG(ctx);
3399 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3400 if (ctx->opcode & 0x00010000) {
3401 /* Special form that does not need any synchronisation */
3402 gen_op_update_riee();
3404 /* XXX: we need to update nip before the store
3405 * if we enter power saving mode, we will exit the loop
3406 * directly from ppc_store_msr
3408 gen_update_nip(ctx, ctx->nip);
3409 #if defined(TARGET_PPC64)
3411 gen_op_store_msr_32();
3415 /* Must stop the translation as machine state (may have) changed */
3416 /* Note that mtmsrd is not always defined as context-synchronizing */
3417 ctx->exception = POWERPC_EXCP_STOP;
3423 GEN_HANDLER(mtspr, 0x1F, 0x13, 0x0E, 0x00000001, PPC_MISC)
3425 void (*write_cb)(void *opaque, int sprn);
3426 uint32_t sprn = SPR(ctx->opcode);
3428 #if !defined(CONFIG_USER_ONLY)
3429 if (ctx->supervisor == 2)
3430 write_cb = ctx->spr_cb[sprn].hea_write;
3431 else if (ctx->supervisor)
3432 write_cb = ctx->spr_cb[sprn].oea_write;
3435 write_cb = ctx->spr_cb[sprn].uea_write;
3436 if (likely(write_cb != NULL)) {
3437 if (likely(write_cb != SPR_NOACCESS)) {
3438 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3439 (*write_cb)(ctx, sprn);
3441 /* Privilege exception */
3442 if (loglevel != 0) {
3443 fprintf(logfile, "Trying to write privileged spr %d %03x at "
3444 ADDRX "\n", sprn, sprn, ctx->nip);
3446 printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
3447 sprn, sprn, ctx->nip);
3448 GEN_EXCP_PRIVREG(ctx);
3452 if (loglevel != 0) {
3453 fprintf(logfile, "Trying to write invalid spr %d %03x at "
3454 ADDRX "\n", sprn, sprn, ctx->nip);
3456 printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
3457 sprn, sprn, ctx->nip);
3458 GEN_EXCP(ctx, POWERPC_EXCP_PROGRAM,
3459 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_SPR);
3463 /*** Cache management ***/
3465 GEN_HANDLER(dcbf, 0x1F, 0x16, 0x02, 0x03C00001, PPC_CACHE)
3467 /* XXX: specification says this is treated as a load by the MMU */
3468 gen_addr_reg_index(ctx);
3472 /* dcbi (Supervisor only) */
3473 GEN_HANDLER(dcbi, 0x1F, 0x16, 0x0E, 0x03E00001, PPC_CACHE)
3475 #if defined(CONFIG_USER_ONLY)
3476 GEN_EXCP_PRIVOPC(ctx);
3478 if (unlikely(!ctx->supervisor)) {
3479 GEN_EXCP_PRIVOPC(ctx);
3482 gen_addr_reg_index(ctx);
3483 /* XXX: specification says this should be treated as a store by the MMU */
3490 GEN_HANDLER(dcbst, 0x1F, 0x16, 0x01, 0x03E00001, PPC_CACHE)
3492 /* XXX: specification say this is treated as a load by the MMU */
3493 gen_addr_reg_index(ctx);
3498 GEN_HANDLER(dcbt, 0x1F, 0x16, 0x08, 0x02000001, PPC_CACHE)
3500 /* interpreted as no-op */
3501 /* XXX: specification say this is treated as a load by the MMU
3502 * but does not generate any exception
3507 GEN_HANDLER(dcbtst, 0x1F, 0x16, 0x07, 0x02000001, PPC_CACHE)
3509 /* interpreted as no-op */
3510 /* XXX: specification say this is treated as a load by the MMU
3511 * but does not generate any exception
3516 #define op_dcbz(n) (*gen_op_dcbz[n][ctx->mem_idx])()
3517 static GenOpFunc *gen_op_dcbz[4][NB_MEM_FUNCS] = {
3518 /* 32 bytes cache line size */
3520 #define gen_op_dcbz_l32_le_raw gen_op_dcbz_l32_raw
3521 #define gen_op_dcbz_l32_le_user gen_op_dcbz_l32_user
3522 #define gen_op_dcbz_l32_le_kernel gen_op_dcbz_l32_kernel
3523 #define gen_op_dcbz_l32_le_hypv gen_op_dcbz_l32_hypv
3524 #define gen_op_dcbz_l32_le_64_raw gen_op_dcbz_l32_64_raw
3525 #define gen_op_dcbz_l32_le_64_user gen_op_dcbz_l32_64_user
3526 #define gen_op_dcbz_l32_le_64_kernel gen_op_dcbz_l32_64_kernel
3527 #define gen_op_dcbz_l32_le_64_hypv gen_op_dcbz_l32_64_hypv
3528 GEN_MEM_FUNCS(dcbz_l32),
3530 /* 64 bytes cache line size */
3532 #define gen_op_dcbz_l64_le_raw gen_op_dcbz_l64_raw
3533 #define gen_op_dcbz_l64_le_user gen_op_dcbz_l64_user
3534 #define gen_op_dcbz_l64_le_kernel gen_op_dcbz_l64_kernel
3535 #define gen_op_dcbz_l64_le_hypv gen_op_dcbz_l64_hypv
3536 #define gen_op_dcbz_l64_le_64_raw gen_op_dcbz_l64_64_raw
3537 #define gen_op_dcbz_l64_le_64_user gen_op_dcbz_l64_64_user
3538 #define gen_op_dcbz_l64_le_64_kernel gen_op_dcbz_l64_64_kernel
3539 #define gen_op_dcbz_l64_le_64_hypv gen_op_dcbz_l64_64_hypv
3540 GEN_MEM_FUNCS(dcbz_l64),
3542 /* 128 bytes cache line size */
3544 #define gen_op_dcbz_l128_le_raw gen_op_dcbz_l128_raw
3545 #define gen_op_dcbz_l128_le_user gen_op_dcbz_l128_user
3546 #define gen_op_dcbz_l128_le_kernel gen_op_dcbz_l128_kernel
3547 #define gen_op_dcbz_l128_le_hypv gen_op_dcbz_l128_hypv
3548 #define gen_op_dcbz_l128_le_64_raw gen_op_dcbz_l128_64_raw
3549 #define gen_op_dcbz_l128_le_64_user gen_op_dcbz_l128_64_user
3550 #define gen_op_dcbz_l128_le_64_kernel gen_op_dcbz_l128_64_kernel
3551 #define gen_op_dcbz_l128_le_64_hypv gen_op_dcbz_l128_64_hypv
3552 GEN_MEM_FUNCS(dcbz_l128),
3554 /* tunable cache line size */
3556 #define gen_op_dcbz_le_raw gen_op_dcbz_raw
3557 #define gen_op_dcbz_le_user gen_op_dcbz_user
3558 #define gen_op_dcbz_le_kernel gen_op_dcbz_kernel
3559 #define gen_op_dcbz_le_hypv gen_op_dcbz_hypv
3560 #define gen_op_dcbz_le_64_raw gen_op_dcbz_64_raw
3561 #define gen_op_dcbz_le_64_user gen_op_dcbz_64_user
3562 #define gen_op_dcbz_le_64_kernel gen_op_dcbz_64_kernel
3563 #define gen_op_dcbz_le_64_hypv gen_op_dcbz_64_hypv
3564 GEN_MEM_FUNCS(dcbz),
3568 static always_inline void handler_dcbz (DisasContext *ctx,
3569 int dcache_line_size)
3573 switch (dcache_line_size) {
3590 GEN_HANDLER(dcbz, 0x1F, 0x16, 0x1F, 0x03E00001, PPC_CACHE_DCBZ)
3592 gen_addr_reg_index(ctx);
3593 handler_dcbz(ctx, ctx->dcache_line_size);
3594 gen_op_check_reservation();
3597 GEN_HANDLER2(dcbz_970, "dcbz", 0x1F, 0x16, 0x1F, 0x03C00001, PPC_CACHE_DCBZT)
3599 gen_addr_reg_index(ctx);
3600 if (ctx->opcode & 0x00200000)
3601 handler_dcbz(ctx, ctx->dcache_line_size);
3603 handler_dcbz(ctx, -1);
3604 gen_op_check_reservation();
3608 #define op_icbi() (*gen_op_icbi[ctx->mem_idx])()
3609 #define gen_op_icbi_le_raw gen_op_icbi_raw
3610 #define gen_op_icbi_le_user gen_op_icbi_user
3611 #define gen_op_icbi_le_kernel gen_op_icbi_kernel
3612 #define gen_op_icbi_le_hypv gen_op_icbi_hypv
3613 #define gen_op_icbi_le_64_raw gen_op_icbi_64_raw
3614 #define gen_op_icbi_le_64_user gen_op_icbi_64_user
3615 #define gen_op_icbi_le_64_kernel gen_op_icbi_64_kernel
3616 #define gen_op_icbi_le_64_hypv gen_op_icbi_64_hypv
3617 static GenOpFunc *gen_op_icbi[NB_MEM_FUNCS] = {
3618 GEN_MEM_FUNCS(icbi),
3621 GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
3623 /* NIP cannot be restored if the memory exception comes from an helper */
3624 gen_update_nip(ctx, ctx->nip - 4);
3625 gen_addr_reg_index(ctx);
3631 GEN_HANDLER(dcba, 0x1F, 0x16, 0x17, 0x03E00001, PPC_CACHE_DCBA)
3633 /* interpreted as no-op */
3634 /* XXX: specification say this is treated as a store by the MMU
3635 * but does not generate any exception
3639 /*** Segment register manipulation ***/
3640 /* Supervisor only: */
3642 GEN_HANDLER(mfsr, 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT)
3644 #if defined(CONFIG_USER_ONLY)
3645 GEN_EXCP_PRIVREG(ctx);
3647 if (unlikely(!ctx->supervisor)) {
3648 GEN_EXCP_PRIVREG(ctx);
3651 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3653 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3658 GEN_HANDLER(mfsrin, 0x1F, 0x13, 0x14, 0x001F0001, PPC_SEGMENT)
3660 #if defined(CONFIG_USER_ONLY)
3661 GEN_EXCP_PRIVREG(ctx);
3663 if (unlikely(!ctx->supervisor)) {
3664 GEN_EXCP_PRIVREG(ctx);
3667 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3670 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3675 GEN_HANDLER(mtsr, 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT)
3677 #if defined(CONFIG_USER_ONLY)
3678 GEN_EXCP_PRIVREG(ctx);
3680 if (unlikely(!ctx->supervisor)) {
3681 GEN_EXCP_PRIVREG(ctx);
3684 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3685 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3691 GEN_HANDLER(mtsrin, 0x1F, 0x12, 0x07, 0x001F0001, PPC_SEGMENT)
3693 #if defined(CONFIG_USER_ONLY)
3694 GEN_EXCP_PRIVREG(ctx);
3696 if (unlikely(!ctx->supervisor)) {
3697 GEN_EXCP_PRIVREG(ctx);
3700 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3701 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3707 #if defined(TARGET_PPC64)
3708 /* Specific implementation for PowerPC 64 "bridge" emulation using SLB */
3710 GEN_HANDLER2(mfsr_64b, "mfsr", 0x1F, 0x13, 0x12, 0x0010F801, PPC_SEGMENT_64B)
3712 #if defined(CONFIG_USER_ONLY)
3713 GEN_EXCP_PRIVREG(ctx);
3715 if (unlikely(!ctx->supervisor)) {
3716 GEN_EXCP_PRIVREG(ctx);
3719 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3721 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3726 GEN_HANDLER2(mfsrin_64b, "mfsrin", 0x1F, 0x13, 0x14, 0x001F0001,
3729 #if defined(CONFIG_USER_ONLY)
3730 GEN_EXCP_PRIVREG(ctx);
3732 if (unlikely(!ctx->supervisor)) {
3733 GEN_EXCP_PRIVREG(ctx);
3736 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3739 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3744 GEN_HANDLER2(mtsr_64b, "mtsr", 0x1F, 0x12, 0x06, 0x0010F801, PPC_SEGMENT_64B)
3746 #if defined(CONFIG_USER_ONLY)
3747 GEN_EXCP_PRIVREG(ctx);
3749 if (unlikely(!ctx->supervisor)) {
3750 GEN_EXCP_PRIVREG(ctx);
3753 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3754 tcg_gen_movi_tl(cpu_T[1], SR(ctx->opcode));
3760 GEN_HANDLER2(mtsrin_64b, "mtsrin", 0x1F, 0x12, 0x07, 0x001F0001,
3763 #if defined(CONFIG_USER_ONLY)
3764 GEN_EXCP_PRIVREG(ctx);
3766 if (unlikely(!ctx->supervisor)) {
3767 GEN_EXCP_PRIVREG(ctx);
3770 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
3771 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3776 #endif /* defined(TARGET_PPC64) */
3778 /*** Lookaside buffer management ***/
3779 /* Optional & supervisor only: */
3781 GEN_HANDLER(tlbia, 0x1F, 0x12, 0x0B, 0x03FFFC01, PPC_MEM_TLBIA)
3783 #if defined(CONFIG_USER_ONLY)
3784 GEN_EXCP_PRIVOPC(ctx);
3786 if (unlikely(!ctx->supervisor)) {
3787 GEN_EXCP_PRIVOPC(ctx);
3795 GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
3797 #if defined(CONFIG_USER_ONLY)
3798 GEN_EXCP_PRIVOPC(ctx);
3800 if (unlikely(!ctx->supervisor)) {
3801 GEN_EXCP_PRIVOPC(ctx);
3804 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
3805 #if defined(TARGET_PPC64)
3815 GEN_HANDLER(tlbsync, 0x1F, 0x16, 0x11, 0x03FFF801, PPC_MEM_TLBSYNC)
3817 #if defined(CONFIG_USER_ONLY)
3818 GEN_EXCP_PRIVOPC(ctx);
3820 if (unlikely(!ctx->supervisor)) {
3821 GEN_EXCP_PRIVOPC(ctx);
3824 /* This has no effect: it should ensure that all previous
3825 * tlbie have completed
3831 #if defined(TARGET_PPC64)
3833 GEN_HANDLER(slbia, 0x1F, 0x12, 0x0F, 0x03FFFC01, PPC_SLBI)
3835 #if defined(CONFIG_USER_ONLY)
3836 GEN_EXCP_PRIVOPC(ctx);
3838 if (unlikely(!ctx->supervisor)) {
3839 GEN_EXCP_PRIVOPC(ctx);
3847 GEN_HANDLER(slbie, 0x1F, 0x12, 0x0D, 0x03FF0001, PPC_SLBI)
3849 #if defined(CONFIG_USER_ONLY)
3850 GEN_EXCP_PRIVOPC(ctx);
3852 if (unlikely(!ctx->supervisor)) {
3853 GEN_EXCP_PRIVOPC(ctx);
3856 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
3862 /*** External control ***/
3864 #define op_eciwx() (*gen_op_eciwx[ctx->mem_idx])()
3865 #define op_ecowx() (*gen_op_ecowx[ctx->mem_idx])()
3866 static GenOpFunc *gen_op_eciwx[NB_MEM_FUNCS] = {
3867 GEN_MEM_FUNCS(eciwx),
3869 static GenOpFunc *gen_op_ecowx[NB_MEM_FUNCS] = {
3870 GEN_MEM_FUNCS(ecowx),
3874 GEN_HANDLER(eciwx, 0x1F, 0x16, 0x0D, 0x00000001, PPC_EXTERN)
3876 /* Should check EAR[E] & alignment ! */
3877 gen_addr_reg_index(ctx);
3879 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3883 GEN_HANDLER(ecowx, 0x1F, 0x16, 0x09, 0x00000001, PPC_EXTERN)
3885 /* Should check EAR[E] & alignment ! */
3886 gen_addr_reg_index(ctx);
3887 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
3891 /* PowerPC 601 specific instructions */
3893 GEN_HANDLER(abs, 0x1F, 0x08, 0x0B, 0x0000F800, PPC_POWER_BR)
3895 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3897 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3898 if (unlikely(Rc(ctx->opcode) != 0))
3903 GEN_HANDLER(abso, 0x1F, 0x08, 0x1B, 0x0000F800, PPC_POWER_BR)
3905 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3906 gen_op_POWER_abso();
3907 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3908 if (unlikely(Rc(ctx->opcode) != 0))
3913 GEN_HANDLER(clcs, 0x1F, 0x10, 0x13, 0x0000F800, PPC_POWER_BR)
3915 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3916 gen_op_POWER_clcs();
3917 /* Rc=1 sets CR0 to an undefined state */
3918 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3922 GEN_HANDLER(div, 0x1F, 0x0B, 0x0A, 0x00000000, PPC_POWER_BR)
3924 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3925 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3927 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3928 if (unlikely(Rc(ctx->opcode) != 0))
3933 GEN_HANDLER(divo, 0x1F, 0x0B, 0x1A, 0x00000000, PPC_POWER_BR)
3935 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3936 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3937 gen_op_POWER_divo();
3938 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3939 if (unlikely(Rc(ctx->opcode) != 0))
3944 GEN_HANDLER(divs, 0x1F, 0x0B, 0x0B, 0x00000000, PPC_POWER_BR)
3946 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3947 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3948 gen_op_POWER_divs();
3949 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3950 if (unlikely(Rc(ctx->opcode) != 0))
3954 /* divso - divso. */
3955 GEN_HANDLER(divso, 0x1F, 0x0B, 0x1B, 0x00000000, PPC_POWER_BR)
3957 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3958 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3959 gen_op_POWER_divso();
3960 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3961 if (unlikely(Rc(ctx->opcode) != 0))
3966 GEN_HANDLER(doz, 0x1F, 0x08, 0x08, 0x00000000, PPC_POWER_BR)
3968 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3969 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3971 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3972 if (unlikely(Rc(ctx->opcode) != 0))
3977 GEN_HANDLER(dozo, 0x1F, 0x08, 0x18, 0x00000000, PPC_POWER_BR)
3979 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3980 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
3981 gen_op_POWER_dozo();
3982 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3983 if (unlikely(Rc(ctx->opcode) != 0))
3988 GEN_HANDLER(dozi, 0x09, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
3990 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
3991 tcg_gen_movi_tl(cpu_T[1], SIMM(ctx->opcode));
3993 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
3996 /* As lscbx load from memory byte after byte, it's always endian safe.
3997 * Original POWER is 32 bits only, define 64 bits ops as 32 bits ones
3999 #define op_POWER_lscbx(start, ra, rb) \
4000 (*gen_op_POWER_lscbx[ctx->mem_idx])(start, ra, rb)
4001 #define gen_op_POWER_lscbx_64_raw gen_op_POWER_lscbx_raw
4002 #define gen_op_POWER_lscbx_64_user gen_op_POWER_lscbx_user
4003 #define gen_op_POWER_lscbx_64_kernel gen_op_POWER_lscbx_kernel
4004 #define gen_op_POWER_lscbx_64_hypv gen_op_POWER_lscbx_hypv
4005 #define gen_op_POWER_lscbx_le_raw gen_op_POWER_lscbx_raw
4006 #define gen_op_POWER_lscbx_le_user gen_op_POWER_lscbx_user
4007 #define gen_op_POWER_lscbx_le_kernel gen_op_POWER_lscbx_kernel
4008 #define gen_op_POWER_lscbx_le_hypv gen_op_POWER_lscbx_hypv
4009 #define gen_op_POWER_lscbx_le_64_raw gen_op_POWER_lscbx_raw
4010 #define gen_op_POWER_lscbx_le_64_user gen_op_POWER_lscbx_user
4011 #define gen_op_POWER_lscbx_le_64_kernel gen_op_POWER_lscbx_kernel
4012 #define gen_op_POWER_lscbx_le_64_hypv gen_op_POWER_lscbx_hypv
4013 static GenOpFunc3 *gen_op_POWER_lscbx[NB_MEM_FUNCS] = {
4014 GEN_MEM_FUNCS(POWER_lscbx),
4017 /* lscbx - lscbx. */
4018 GEN_HANDLER(lscbx, 0x1F, 0x15, 0x08, 0x00000000, PPC_POWER_BR)
4020 int ra = rA(ctx->opcode);
4021 int rb = rB(ctx->opcode);
4023 gen_addr_reg_index(ctx);
4027 /* NIP cannot be restored if the memory exception comes from an helper */
4028 gen_update_nip(ctx, ctx->nip - 4);
4029 gen_op_load_xer_bc();
4030 gen_op_load_xer_cmp();
4031 op_POWER_lscbx(rD(ctx->opcode), ra, rb);
4032 gen_op_store_xer_bc();
4033 if (unlikely(Rc(ctx->opcode) != 0))
4037 /* maskg - maskg. */
4038 GEN_HANDLER(maskg, 0x1F, 0x1D, 0x00, 0x00000000, PPC_POWER_BR)
4040 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4041 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4042 gen_op_POWER_maskg();
4043 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4044 if (unlikely(Rc(ctx->opcode) != 0))
4048 /* maskir - maskir. */
4049 GEN_HANDLER(maskir, 0x1F, 0x1D, 0x10, 0x00000000, PPC_POWER_BR)
4051 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4052 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4053 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4054 gen_op_POWER_maskir();
4055 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4056 if (unlikely(Rc(ctx->opcode) != 0))
4061 GEN_HANDLER(mul, 0x1F, 0x0B, 0x03, 0x00000000, PPC_POWER_BR)
4063 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4064 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4066 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4067 if (unlikely(Rc(ctx->opcode) != 0))
4072 GEN_HANDLER(mulo, 0x1F, 0x0B, 0x13, 0x00000000, PPC_POWER_BR)
4074 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4075 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4076 gen_op_POWER_mulo();
4077 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4078 if (unlikely(Rc(ctx->opcode) != 0))
4083 GEN_HANDLER(nabs, 0x1F, 0x08, 0x0F, 0x00000000, PPC_POWER_BR)
4085 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4086 gen_op_POWER_nabs();
4087 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4088 if (unlikely(Rc(ctx->opcode) != 0))
4092 /* nabso - nabso. */
4093 GEN_HANDLER(nabso, 0x1F, 0x08, 0x1F, 0x00000000, PPC_POWER_BR)
4095 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4096 gen_op_POWER_nabso();
4097 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4098 if (unlikely(Rc(ctx->opcode) != 0))
4103 GEN_HANDLER(rlmi, 0x16, 0xFF, 0xFF, 0x00000000, PPC_POWER_BR)
4107 mb = MB(ctx->opcode);
4108 me = ME(ctx->opcode);
4109 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4110 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4111 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4112 gen_op_POWER_rlmi(MASK(mb, me), ~MASK(mb, me));
4113 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4114 if (unlikely(Rc(ctx->opcode) != 0))
4119 GEN_HANDLER(rrib, 0x1F, 0x19, 0x10, 0x00000000, PPC_POWER_BR)
4121 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4122 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rA(ctx->opcode)]);
4123 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rB(ctx->opcode)]);
4124 gen_op_POWER_rrib();
4125 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4126 if (unlikely(Rc(ctx->opcode) != 0))
4131 GEN_HANDLER(sle, 0x1F, 0x19, 0x04, 0x00000000, PPC_POWER_BR)
4133 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4134 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4136 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4137 if (unlikely(Rc(ctx->opcode) != 0))
4142 GEN_HANDLER(sleq, 0x1F, 0x19, 0x06, 0x00000000, PPC_POWER_BR)
4144 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4145 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4146 gen_op_POWER_sleq();
4147 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4148 if (unlikely(Rc(ctx->opcode) != 0))
4153 GEN_HANDLER(sliq, 0x1F, 0x18, 0x05, 0x00000000, PPC_POWER_BR)
4155 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4156 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4158 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4159 if (unlikely(Rc(ctx->opcode) != 0))
4163 /* slliq - slliq. */
4164 GEN_HANDLER(slliq, 0x1F, 0x18, 0x07, 0x00000000, PPC_POWER_BR)
4166 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4167 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4168 gen_op_POWER_sleq();
4169 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4170 if (unlikely(Rc(ctx->opcode) != 0))
4175 GEN_HANDLER(sllq, 0x1F, 0x18, 0x06, 0x00000000, PPC_POWER_BR)
4177 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4178 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4179 gen_op_POWER_sllq();
4180 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4181 if (unlikely(Rc(ctx->opcode) != 0))
4186 GEN_HANDLER(slq, 0x1F, 0x18, 0x04, 0x00000000, PPC_POWER_BR)
4188 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4189 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4191 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4192 if (unlikely(Rc(ctx->opcode) != 0))
4196 /* sraiq - sraiq. */
4197 GEN_HANDLER(sraiq, 0x1F, 0x18, 0x1D, 0x00000000, PPC_POWER_BR)
4199 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4200 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4201 gen_op_POWER_sraq();
4202 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4203 if (unlikely(Rc(ctx->opcode) != 0))
4208 GEN_HANDLER(sraq, 0x1F, 0x18, 0x1C, 0x00000000, PPC_POWER_BR)
4210 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4211 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4212 gen_op_POWER_sraq();
4213 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4214 if (unlikely(Rc(ctx->opcode) != 0))
4219 GEN_HANDLER(sre, 0x1F, 0x19, 0x14, 0x00000000, PPC_POWER_BR)
4221 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4222 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4224 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4225 if (unlikely(Rc(ctx->opcode) != 0))
4230 GEN_HANDLER(srea, 0x1F, 0x19, 0x1C, 0x00000000, PPC_POWER_BR)
4232 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4233 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4234 gen_op_POWER_srea();
4235 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4236 if (unlikely(Rc(ctx->opcode) != 0))
4241 GEN_HANDLER(sreq, 0x1F, 0x19, 0x16, 0x00000000, PPC_POWER_BR)
4243 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4244 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4245 gen_op_POWER_sreq();
4246 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4247 if (unlikely(Rc(ctx->opcode) != 0))
4252 GEN_HANDLER(sriq, 0x1F, 0x18, 0x15, 0x00000000, PPC_POWER_BR)
4254 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4255 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4257 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4258 if (unlikely(Rc(ctx->opcode) != 0))
4263 GEN_HANDLER(srliq, 0x1F, 0x18, 0x17, 0x00000000, PPC_POWER_BR)
4265 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4266 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4267 tcg_gen_movi_tl(cpu_T[1], SH(ctx->opcode));
4268 gen_op_POWER_srlq();
4269 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4270 if (unlikely(Rc(ctx->opcode) != 0))
4275 GEN_HANDLER(srlq, 0x1F, 0x18, 0x16, 0x00000000, PPC_POWER_BR)
4277 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4278 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4279 gen_op_POWER_srlq();
4280 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4281 if (unlikely(Rc(ctx->opcode) != 0))
4286 GEN_HANDLER(srq, 0x1F, 0x18, 0x14, 0x00000000, PPC_POWER_BR)
4288 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
4289 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
4291 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
4292 if (unlikely(Rc(ctx->opcode) != 0))
4296 /* PowerPC 602 specific instructions */
4298 GEN_HANDLER(dsa, 0x1F, 0x14, 0x13, 0x03FFF801, PPC_602_SPEC)
4301 GEN_EXCP_INVAL(ctx);
4305 GEN_HANDLER(esa, 0x1F, 0x14, 0x12, 0x03FFF801, PPC_602_SPEC)
4308 GEN_EXCP_INVAL(ctx);
4312 GEN_HANDLER(mfrom, 0x1F, 0x09, 0x08, 0x03E0F801, PPC_602_SPEC)
4314 #if defined(CONFIG_USER_ONLY)
4315 GEN_EXCP_PRIVOPC(ctx);
4317 if (unlikely(!ctx->supervisor)) {
4318 GEN_EXCP_PRIVOPC(ctx);
4321 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4323 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4327 /* 602 - 603 - G2 TLB management */
4329 GEN_HANDLER2(tlbld_6xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_6xx_TLB)
4331 #if defined(CONFIG_USER_ONLY)
4332 GEN_EXCP_PRIVOPC(ctx);
4334 if (unlikely(!ctx->supervisor)) {
4335 GEN_EXCP_PRIVOPC(ctx);
4338 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4344 GEN_HANDLER2(tlbli_6xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_6xx_TLB)
4346 #if defined(CONFIG_USER_ONLY)
4347 GEN_EXCP_PRIVOPC(ctx);
4349 if (unlikely(!ctx->supervisor)) {
4350 GEN_EXCP_PRIVOPC(ctx);
4353 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4358 /* 74xx TLB management */
4360 GEN_HANDLER2(tlbld_74xx, "tlbld", 0x1F, 0x12, 0x1E, 0x03FF0001, PPC_74xx_TLB)
4362 #if defined(CONFIG_USER_ONLY)
4363 GEN_EXCP_PRIVOPC(ctx);
4365 if (unlikely(!ctx->supervisor)) {
4366 GEN_EXCP_PRIVOPC(ctx);
4369 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4370 gen_op_74xx_tlbld();
4375 GEN_HANDLER2(tlbli_74xx, "tlbli", 0x1F, 0x12, 0x1F, 0x03FF0001, PPC_74xx_TLB)
4377 #if defined(CONFIG_USER_ONLY)
4378 GEN_EXCP_PRIVOPC(ctx);
4380 if (unlikely(!ctx->supervisor)) {
4381 GEN_EXCP_PRIVOPC(ctx);
4384 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rB(ctx->opcode)]);
4385 gen_op_74xx_tlbli();
4389 /* POWER instructions not in PowerPC 601 */
4391 GEN_HANDLER(clf, 0x1F, 0x16, 0x03, 0x03E00000, PPC_POWER)
4393 /* Cache line flush: implemented as no-op */
4397 GEN_HANDLER(cli, 0x1F, 0x16, 0x0F, 0x03E00000, PPC_POWER)
4399 /* Cache line invalidate: privileged and treated as no-op */
4400 #if defined(CONFIG_USER_ONLY)
4401 GEN_EXCP_PRIVOPC(ctx);
4403 if (unlikely(!ctx->supervisor)) {
4404 GEN_EXCP_PRIVOPC(ctx);
4411 GEN_HANDLER(dclst, 0x1F, 0x16, 0x13, 0x03E00000, PPC_POWER)
4413 /* Data cache line store: treated as no-op */
4416 GEN_HANDLER(mfsri, 0x1F, 0x13, 0x13, 0x00000001, PPC_POWER)
4418 #if defined(CONFIG_USER_ONLY)
4419 GEN_EXCP_PRIVOPC(ctx);
4421 if (unlikely(!ctx->supervisor)) {
4422 GEN_EXCP_PRIVOPC(ctx);
4425 int ra = rA(ctx->opcode);
4426 int rd = rD(ctx->opcode);
4428 gen_addr_reg_index(ctx);
4429 gen_op_POWER_mfsri();
4430 tcg_gen_mov_tl(cpu_gpr[rd], cpu_T[0]);
4431 if (ra != 0 && ra != rd)
4432 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[1]);
4436 GEN_HANDLER(rac, 0x1F, 0x12, 0x19, 0x00000001, PPC_POWER)
4438 #if defined(CONFIG_USER_ONLY)
4439 GEN_EXCP_PRIVOPC(ctx);
4441 if (unlikely(!ctx->supervisor)) {
4442 GEN_EXCP_PRIVOPC(ctx);
4445 gen_addr_reg_index(ctx);
4447 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4451 GEN_HANDLER(rfsvc, 0x13, 0x12, 0x02, 0x03FFF0001, PPC_POWER)
4453 #if defined(CONFIG_USER_ONLY)
4454 GEN_EXCP_PRIVOPC(ctx);
4456 if (unlikely(!ctx->supervisor)) {
4457 GEN_EXCP_PRIVOPC(ctx);
4460 gen_op_POWER_rfsvc();
4465 /* svc is not implemented for now */
4467 /* POWER2 specific instructions */
4468 /* Quad manipulation (load/store two floats at a time) */
4469 /* Original POWER2 is 32 bits only, define 64 bits ops as 32 bits ones */
4470 #define op_POWER2_lfq() (*gen_op_POWER2_lfq[ctx->mem_idx])()
4471 #define op_POWER2_stfq() (*gen_op_POWER2_stfq[ctx->mem_idx])()
4472 #define gen_op_POWER2_lfq_64_raw gen_op_POWER2_lfq_raw
4473 #define gen_op_POWER2_lfq_64_user gen_op_POWER2_lfq_user
4474 #define gen_op_POWER2_lfq_64_kernel gen_op_POWER2_lfq_kernel
4475 #define gen_op_POWER2_lfq_64_hypv gen_op_POWER2_lfq_hypv
4476 #define gen_op_POWER2_lfq_le_64_raw gen_op_POWER2_lfq_le_raw
4477 #define gen_op_POWER2_lfq_le_64_user gen_op_POWER2_lfq_le_user
4478 #define gen_op_POWER2_lfq_le_64_kernel gen_op_POWER2_lfq_le_kernel
4479 #define gen_op_POWER2_lfq_le_64_hypv gen_op_POWER2_lfq_le_hypv
4480 #define gen_op_POWER2_stfq_64_raw gen_op_POWER2_stfq_raw
4481 #define gen_op_POWER2_stfq_64_user gen_op_POWER2_stfq_user
4482 #define gen_op_POWER2_stfq_64_kernel gen_op_POWER2_stfq_kernel
4483 #define gen_op_POWER2_stfq_64_hypv gen_op_POWER2_stfq_hypv
4484 #define gen_op_POWER2_stfq_le_64_raw gen_op_POWER2_stfq_le_raw
4485 #define gen_op_POWER2_stfq_le_64_user gen_op_POWER2_stfq_le_user
4486 #define gen_op_POWER2_stfq_le_64_kernel gen_op_POWER2_stfq_le_kernel
4487 #define gen_op_POWER2_stfq_le_64_hypv gen_op_POWER2_stfq_le_hypv
4488 static GenOpFunc *gen_op_POWER2_lfq[NB_MEM_FUNCS] = {
4489 GEN_MEM_FUNCS(POWER2_lfq),
4491 static GenOpFunc *gen_op_POWER2_stfq[NB_MEM_FUNCS] = {
4492 GEN_MEM_FUNCS(POWER2_stfq),
4496 GEN_HANDLER(lfq, 0x38, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4498 /* NIP cannot be restored if the memory exception comes from an helper */
4499 gen_update_nip(ctx, ctx->nip - 4);
4500 gen_addr_imm_index(ctx, 0);
4502 gen_op_store_FT0_fpr(rD(ctx->opcode));
4503 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4507 GEN_HANDLER(lfqu, 0x39, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4509 int ra = rA(ctx->opcode);
4511 /* NIP cannot be restored if the memory exception comes from an helper */
4512 gen_update_nip(ctx, ctx->nip - 4);
4513 gen_addr_imm_index(ctx, 0);
4515 gen_op_store_FT0_fpr(rD(ctx->opcode));
4516 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4518 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4522 GEN_HANDLER(lfqux, 0x1F, 0x17, 0x19, 0x00000001, PPC_POWER2)
4524 int ra = rA(ctx->opcode);
4526 /* NIP cannot be restored if the memory exception comes from an helper */
4527 gen_update_nip(ctx, ctx->nip - 4);
4528 gen_addr_reg_index(ctx);
4530 gen_op_store_FT0_fpr(rD(ctx->opcode));
4531 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4533 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4537 GEN_HANDLER(lfqx, 0x1F, 0x17, 0x18, 0x00000001, PPC_POWER2)
4539 /* NIP cannot be restored if the memory exception comes from an helper */
4540 gen_update_nip(ctx, ctx->nip - 4);
4541 gen_addr_reg_index(ctx);
4543 gen_op_store_FT0_fpr(rD(ctx->opcode));
4544 gen_op_store_FT1_fpr(rD(ctx->opcode) + 1);
4548 GEN_HANDLER(stfq, 0x3C, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4550 /* NIP cannot be restored if the memory exception comes from an helper */
4551 gen_update_nip(ctx, ctx->nip - 4);
4552 gen_addr_imm_index(ctx, 0);
4553 gen_op_load_fpr_FT0(rS(ctx->opcode));
4554 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4559 GEN_HANDLER(stfqu, 0x3D, 0xFF, 0xFF, 0x00000003, PPC_POWER2)
4561 int ra = rA(ctx->opcode);
4563 /* NIP cannot be restored if the memory exception comes from an helper */
4564 gen_update_nip(ctx, ctx->nip - 4);
4565 gen_addr_imm_index(ctx, 0);
4566 gen_op_load_fpr_FT0(rS(ctx->opcode));
4567 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4570 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4574 GEN_HANDLER(stfqux, 0x1F, 0x17, 0x1D, 0x00000001, PPC_POWER2)
4576 int ra = rA(ctx->opcode);
4578 /* NIP cannot be restored if the memory exception comes from an helper */
4579 gen_update_nip(ctx, ctx->nip - 4);
4580 gen_addr_reg_index(ctx);
4581 gen_op_load_fpr_FT0(rS(ctx->opcode));
4582 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4585 tcg_gen_mov_tl(cpu_gpr[ra], cpu_T[0]);
4589 GEN_HANDLER(stfqx, 0x1F, 0x17, 0x1C, 0x00000001, PPC_POWER2)
4591 /* NIP cannot be restored if the memory exception comes from an helper */
4592 gen_update_nip(ctx, ctx->nip - 4);
4593 gen_addr_reg_index(ctx);
4594 gen_op_load_fpr_FT0(rS(ctx->opcode));
4595 gen_op_load_fpr_FT1(rS(ctx->opcode) + 1);
4599 /* BookE specific instructions */
4600 /* XXX: not implemented on 440 ? */
4601 GEN_HANDLER(mfapidi, 0x1F, 0x13, 0x08, 0x0000F801, PPC_MFAPIDI)
4604 GEN_EXCP_INVAL(ctx);
4607 /* XXX: not implemented on 440 ? */
4608 GEN_HANDLER(tlbiva, 0x1F, 0x12, 0x18, 0x03FFF801, PPC_TLBIVA)
4610 #if defined(CONFIG_USER_ONLY)
4611 GEN_EXCP_PRIVOPC(ctx);
4613 if (unlikely(!ctx->supervisor)) {
4614 GEN_EXCP_PRIVOPC(ctx);
4617 gen_addr_reg_index(ctx);
4618 /* Use the same micro-ops as for tlbie */
4619 #if defined(TARGET_PPC64)
4628 /* All 405 MAC instructions are translated here */
4629 static always_inline void gen_405_mulladd_insn (DisasContext *ctx,
4631 int ra, int rb, int rt, int Rc)
4633 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[ra]);
4634 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rb]);
4635 switch (opc3 & 0x0D) {
4637 /* macchw - macchw. - macchwo - macchwo. */
4638 /* macchws - macchws. - macchwso - macchwso. */
4639 /* nmacchw - nmacchw. - nmacchwo - nmacchwo. */
4640 /* nmacchws - nmacchws. - nmacchwso - nmacchwso. */
4641 /* mulchw - mulchw. */
4642 gen_op_405_mulchw();
4645 /* macchwu - macchwu. - macchwuo - macchwuo. */
4646 /* macchwsu - macchwsu. - macchwsuo - macchwsuo. */
4647 /* mulchwu - mulchwu. */
4648 gen_op_405_mulchwu();
4651 /* machhw - machhw. - machhwo - machhwo. */
4652 /* machhws - machhws. - machhwso - machhwso. */
4653 /* nmachhw - nmachhw. - nmachhwo - nmachhwo. */
4654 /* nmachhws - nmachhws. - nmachhwso - nmachhwso. */
4655 /* mulhhw - mulhhw. */
4656 gen_op_405_mulhhw();
4659 /* machhwu - machhwu. - machhwuo - machhwuo. */
4660 /* machhwsu - machhwsu. - machhwsuo - machhwsuo. */
4661 /* mulhhwu - mulhhwu. */
4662 gen_op_405_mulhhwu();
4665 /* maclhw - maclhw. - maclhwo - maclhwo. */
4666 /* maclhws - maclhws. - maclhwso - maclhwso. */
4667 /* nmaclhw - nmaclhw. - nmaclhwo - nmaclhwo. */
4668 /* nmaclhws - nmaclhws. - nmaclhwso - nmaclhwso. */
4669 /* mullhw - mullhw. */
4670 gen_op_405_mullhw();
4673 /* maclhwu - maclhwu. - maclhwuo - maclhwuo. */
4674 /* maclhwsu - maclhwsu. - maclhwsuo - maclhwsuo. */
4675 /* mullhwu - mullhwu. */
4676 gen_op_405_mullhwu();
4680 /* nmultiply-and-accumulate (0x0E) */
4684 /* (n)multiply-and-accumulate (0x0C - 0x0E) */
4685 tcg_gen_mov_tl(cpu_T[2], cpu_gpr[rt]);
4686 tcg_gen_mov_tl(cpu_T[1], cpu_T[0]);
4687 gen_op_405_add_T0_T2();
4690 /* Check overflow */
4692 gen_op_check_addo();
4694 gen_op_405_check_ovu();
4699 gen_op_405_check_sat();
4701 gen_op_405_check_satu();
4703 tcg_gen_mov_tl(cpu_gpr[rt], cpu_T[0]);
4704 if (unlikely(Rc) != 0) {
4710 #define GEN_MAC_HANDLER(name, opc2, opc3) \
4711 GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_405_MAC) \
4713 gen_405_mulladd_insn(ctx, opc2, opc3, rA(ctx->opcode), rB(ctx->opcode), \
4714 rD(ctx->opcode), Rc(ctx->opcode)); \
4717 /* macchw - macchw. */
4718 GEN_MAC_HANDLER(macchw, 0x0C, 0x05);
4719 /* macchwo - macchwo. */
4720 GEN_MAC_HANDLER(macchwo, 0x0C, 0x15);
4721 /* macchws - macchws. */
4722 GEN_MAC_HANDLER(macchws, 0x0C, 0x07);
4723 /* macchwso - macchwso. */
4724 GEN_MAC_HANDLER(macchwso, 0x0C, 0x17);
4725 /* macchwsu - macchwsu. */
4726 GEN_MAC_HANDLER(macchwsu, 0x0C, 0x06);
4727 /* macchwsuo - macchwsuo. */
4728 GEN_MAC_HANDLER(macchwsuo, 0x0C, 0x16);
4729 /* macchwu - macchwu. */
4730 GEN_MAC_HANDLER(macchwu, 0x0C, 0x04);
4731 /* macchwuo - macchwuo. */
4732 GEN_MAC_HANDLER(macchwuo, 0x0C, 0x14);
4733 /* machhw - machhw. */
4734 GEN_MAC_HANDLER(machhw, 0x0C, 0x01);
4735 /* machhwo - machhwo. */
4736 GEN_MAC_HANDLER(machhwo, 0x0C, 0x11);
4737 /* machhws - machhws. */
4738 GEN_MAC_HANDLER(machhws, 0x0C, 0x03);
4739 /* machhwso - machhwso. */
4740 GEN_MAC_HANDLER(machhwso, 0x0C, 0x13);
4741 /* machhwsu - machhwsu. */
4742 GEN_MAC_HANDLER(machhwsu, 0x0C, 0x02);
4743 /* machhwsuo - machhwsuo. */
4744 GEN_MAC_HANDLER(machhwsuo, 0x0C, 0x12);
4745 /* machhwu - machhwu. */
4746 GEN_MAC_HANDLER(machhwu, 0x0C, 0x00);
4747 /* machhwuo - machhwuo. */
4748 GEN_MAC_HANDLER(machhwuo, 0x0C, 0x10);
4749 /* maclhw - maclhw. */
4750 GEN_MAC_HANDLER(maclhw, 0x0C, 0x0D);
4751 /* maclhwo - maclhwo. */
4752 GEN_MAC_HANDLER(maclhwo, 0x0C, 0x1D);
4753 /* maclhws - maclhws. */
4754 GEN_MAC_HANDLER(maclhws, 0x0C, 0x0F);
4755 /* maclhwso - maclhwso. */
4756 GEN_MAC_HANDLER(maclhwso, 0x0C, 0x1F);
4757 /* maclhwu - maclhwu. */
4758 GEN_MAC_HANDLER(maclhwu, 0x0C, 0x0C);
4759 /* maclhwuo - maclhwuo. */
4760 GEN_MAC_HANDLER(maclhwuo, 0x0C, 0x1C);
4761 /* maclhwsu - maclhwsu. */
4762 GEN_MAC_HANDLER(maclhwsu, 0x0C, 0x0E);
4763 /* maclhwsuo - maclhwsuo. */
4764 GEN_MAC_HANDLER(maclhwsuo, 0x0C, 0x1E);
4765 /* nmacchw - nmacchw. */
4766 GEN_MAC_HANDLER(nmacchw, 0x0E, 0x05);
4767 /* nmacchwo - nmacchwo. */
4768 GEN_MAC_HANDLER(nmacchwo, 0x0E, 0x15);
4769 /* nmacchws - nmacchws. */
4770 GEN_MAC_HANDLER(nmacchws, 0x0E, 0x07);
4771 /* nmacchwso - nmacchwso. */
4772 GEN_MAC_HANDLER(nmacchwso, 0x0E, 0x17);
4773 /* nmachhw - nmachhw. */
4774 GEN_MAC_HANDLER(nmachhw, 0x0E, 0x01);
4775 /* nmachhwo - nmachhwo. */
4776 GEN_MAC_HANDLER(nmachhwo, 0x0E, 0x11);
4777 /* nmachhws - nmachhws. */
4778 GEN_MAC_HANDLER(nmachhws, 0x0E, 0x03);
4779 /* nmachhwso - nmachhwso. */
4780 GEN_MAC_HANDLER(nmachhwso, 0x0E, 0x13);
4781 /* nmaclhw - nmaclhw. */
4782 GEN_MAC_HANDLER(nmaclhw, 0x0E, 0x0D);
4783 /* nmaclhwo - nmaclhwo. */
4784 GEN_MAC_HANDLER(nmaclhwo, 0x0E, 0x1D);
4785 /* nmaclhws - nmaclhws. */
4786 GEN_MAC_HANDLER(nmaclhws, 0x0E, 0x0F);
4787 /* nmaclhwso - nmaclhwso. */
4788 GEN_MAC_HANDLER(nmaclhwso, 0x0E, 0x1F);
4790 /* mulchw - mulchw. */
4791 GEN_MAC_HANDLER(mulchw, 0x08, 0x05);
4792 /* mulchwu - mulchwu. */
4793 GEN_MAC_HANDLER(mulchwu, 0x08, 0x04);
4794 /* mulhhw - mulhhw. */
4795 GEN_MAC_HANDLER(mulhhw, 0x08, 0x01);
4796 /* mulhhwu - mulhhwu. */
4797 GEN_MAC_HANDLER(mulhhwu, 0x08, 0x00);
4798 /* mullhw - mullhw. */
4799 GEN_MAC_HANDLER(mullhw, 0x08, 0x0D);
4800 /* mullhwu - mullhwu. */
4801 GEN_MAC_HANDLER(mullhwu, 0x08, 0x0C);
4804 GEN_HANDLER(mfdcr, 0x1F, 0x03, 0x0A, 0x00000001, PPC_DCR)
4806 #if defined(CONFIG_USER_ONLY)
4807 GEN_EXCP_PRIVREG(ctx);
4809 uint32_t dcrn = SPR(ctx->opcode);
4811 if (unlikely(!ctx->supervisor)) {
4812 GEN_EXCP_PRIVREG(ctx);
4815 tcg_gen_movi_tl(cpu_T[0], dcrn);
4817 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4822 GEN_HANDLER(mtdcr, 0x1F, 0x03, 0x0E, 0x00000001, PPC_DCR)
4824 #if defined(CONFIG_USER_ONLY)
4825 GEN_EXCP_PRIVREG(ctx);
4827 uint32_t dcrn = SPR(ctx->opcode);
4829 if (unlikely(!ctx->supervisor)) {
4830 GEN_EXCP_PRIVREG(ctx);
4833 tcg_gen_movi_tl(cpu_T[0], dcrn);
4834 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4840 /* XXX: not implemented on 440 ? */
4841 GEN_HANDLER(mfdcrx, 0x1F, 0x03, 0x08, 0x00000000, PPC_DCRX)
4843 #if defined(CONFIG_USER_ONLY)
4844 GEN_EXCP_PRIVREG(ctx);
4846 if (unlikely(!ctx->supervisor)) {
4847 GEN_EXCP_PRIVREG(ctx);
4850 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4852 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4853 /* Note: Rc update flag set leads to undefined state of Rc0 */
4858 /* XXX: not implemented on 440 ? */
4859 GEN_HANDLER(mtdcrx, 0x1F, 0x03, 0x0C, 0x00000000, PPC_DCRX)
4861 #if defined(CONFIG_USER_ONLY)
4862 GEN_EXCP_PRIVREG(ctx);
4864 if (unlikely(!ctx->supervisor)) {
4865 GEN_EXCP_PRIVREG(ctx);
4868 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4869 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4871 /* Note: Rc update flag set leads to undefined state of Rc0 */
4875 /* mfdcrux (PPC 460) : user-mode access to DCR */
4876 GEN_HANDLER(mfdcrux, 0x1F, 0x03, 0x09, 0x00000000, PPC_DCRUX)
4878 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4880 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4881 /* Note: Rc update flag set leads to undefined state of Rc0 */
4884 /* mtdcrux (PPC 460) : user-mode access to DCR */
4885 GEN_HANDLER(mtdcrux, 0x1F, 0x03, 0x0D, 0x00000000, PPC_DCRUX)
4887 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
4888 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
4890 /* Note: Rc update flag set leads to undefined state of Rc0 */
4894 GEN_HANDLER(dccci, 0x1F, 0x06, 0x0E, 0x03E00001, PPC_4xx_COMMON)
4896 #if defined(CONFIG_USER_ONLY)
4897 GEN_EXCP_PRIVOPC(ctx);
4899 if (unlikely(!ctx->supervisor)) {
4900 GEN_EXCP_PRIVOPC(ctx);
4903 /* interpreted as no-op */
4908 GEN_HANDLER(dcread, 0x1F, 0x06, 0x0F, 0x00000001, PPC_4xx_COMMON)
4910 #if defined(CONFIG_USER_ONLY)
4911 GEN_EXCP_PRIVOPC(ctx);
4913 if (unlikely(!ctx->supervisor)) {
4914 GEN_EXCP_PRIVOPC(ctx);
4917 gen_addr_reg_index(ctx);
4919 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
4924 GEN_HANDLER2(icbt_40x, "icbt", 0x1F, 0x06, 0x08, 0x03E00001, PPC_40x_ICBT)
4926 /* interpreted as no-op */
4927 /* XXX: specification say this is treated as a load by the MMU
4928 * but does not generate any exception
4933 GEN_HANDLER(iccci, 0x1F, 0x06, 0x1E, 0x00000001, PPC_4xx_COMMON)
4935 #if defined(CONFIG_USER_ONLY)
4936 GEN_EXCP_PRIVOPC(ctx);
4938 if (unlikely(!ctx->supervisor)) {
4939 GEN_EXCP_PRIVOPC(ctx);
4942 /* interpreted as no-op */
4947 GEN_HANDLER(icread, 0x1F, 0x06, 0x1F, 0x03E00001, PPC_4xx_COMMON)
4949 #if defined(CONFIG_USER_ONLY)
4950 GEN_EXCP_PRIVOPC(ctx);
4952 if (unlikely(!ctx->supervisor)) {
4953 GEN_EXCP_PRIVOPC(ctx);
4956 /* interpreted as no-op */
4960 /* rfci (supervisor only) */
4961 GEN_HANDLER2(rfci_40x, "rfci", 0x13, 0x13, 0x01, 0x03FF8001, PPC_40x_EXCP)
4963 #if defined(CONFIG_USER_ONLY)
4964 GEN_EXCP_PRIVOPC(ctx);
4966 if (unlikely(!ctx->supervisor)) {
4967 GEN_EXCP_PRIVOPC(ctx);
4970 /* Restore CPU state */
4976 GEN_HANDLER(rfci, 0x13, 0x13, 0x01, 0x03FF8001, PPC_BOOKE)
4978 #if defined(CONFIG_USER_ONLY)
4979 GEN_EXCP_PRIVOPC(ctx);
4981 if (unlikely(!ctx->supervisor)) {
4982 GEN_EXCP_PRIVOPC(ctx);
4985 /* Restore CPU state */
4991 /* BookE specific */
4992 /* XXX: not implemented on 440 ? */
4993 GEN_HANDLER(rfdi, 0x13, 0x07, 0x01, 0x03FF8001, PPC_RFDI)
4995 #if defined(CONFIG_USER_ONLY)
4996 GEN_EXCP_PRIVOPC(ctx);
4998 if (unlikely(!ctx->supervisor)) {
4999 GEN_EXCP_PRIVOPC(ctx);
5002 /* Restore CPU state */
5008 /* XXX: not implemented on 440 ? */
5009 GEN_HANDLER(rfmci, 0x13, 0x06, 0x01, 0x03FF8001, PPC_RFMCI)
5011 #if defined(CONFIG_USER_ONLY)
5012 GEN_EXCP_PRIVOPC(ctx);
5014 if (unlikely(!ctx->supervisor)) {
5015 GEN_EXCP_PRIVOPC(ctx);
5018 /* Restore CPU state */
5024 /* TLB management - PowerPC 405 implementation */
5026 GEN_HANDLER2(tlbre_40x, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_40x_TLB)
5028 #if defined(CONFIG_USER_ONLY)
5029 GEN_EXCP_PRIVOPC(ctx);
5031 if (unlikely(!ctx->supervisor)) {
5032 GEN_EXCP_PRIVOPC(ctx);
5035 switch (rB(ctx->opcode)) {
5037 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5038 gen_op_4xx_tlbre_hi();
5039 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5042 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5043 gen_op_4xx_tlbre_lo();
5044 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5047 GEN_EXCP_INVAL(ctx);
5053 /* tlbsx - tlbsx. */
5054 GEN_HANDLER2(tlbsx_40x, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_40x_TLB)
5056 #if defined(CONFIG_USER_ONLY)
5057 GEN_EXCP_PRIVOPC(ctx);
5059 if (unlikely(!ctx->supervisor)) {
5060 GEN_EXCP_PRIVOPC(ctx);
5063 gen_addr_reg_index(ctx);
5065 if (Rc(ctx->opcode))
5066 gen_op_4xx_tlbsx_check();
5067 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5072 GEN_HANDLER2(tlbwe_40x, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_40x_TLB)
5074 #if defined(CONFIG_USER_ONLY)
5075 GEN_EXCP_PRIVOPC(ctx);
5077 if (unlikely(!ctx->supervisor)) {
5078 GEN_EXCP_PRIVOPC(ctx);
5081 switch (rB(ctx->opcode)) {
5083 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5084 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5085 gen_op_4xx_tlbwe_hi();
5088 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5089 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5090 gen_op_4xx_tlbwe_lo();
5093 GEN_EXCP_INVAL(ctx);
5099 /* TLB management - PowerPC 440 implementation */
5101 GEN_HANDLER2(tlbre_440, "tlbre", 0x1F, 0x12, 0x1D, 0x00000001, PPC_BOOKE)
5103 #if defined(CONFIG_USER_ONLY)
5104 GEN_EXCP_PRIVOPC(ctx);
5106 if (unlikely(!ctx->supervisor)) {
5107 GEN_EXCP_PRIVOPC(ctx);
5110 switch (rB(ctx->opcode)) {
5114 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5115 gen_op_440_tlbre(rB(ctx->opcode));
5116 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5119 GEN_EXCP_INVAL(ctx);
5125 /* tlbsx - tlbsx. */
5126 GEN_HANDLER2(tlbsx_440, "tlbsx", 0x1F, 0x12, 0x1C, 0x00000000, PPC_BOOKE)
5128 #if defined(CONFIG_USER_ONLY)
5129 GEN_EXCP_PRIVOPC(ctx);
5131 if (unlikely(!ctx->supervisor)) {
5132 GEN_EXCP_PRIVOPC(ctx);
5135 gen_addr_reg_index(ctx);
5137 if (Rc(ctx->opcode))
5138 gen_op_4xx_tlbsx_check();
5139 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5144 GEN_HANDLER2(tlbwe_440, "tlbwe", 0x1F, 0x12, 0x1E, 0x00000001, PPC_BOOKE)
5146 #if defined(CONFIG_USER_ONLY)
5147 GEN_EXCP_PRIVOPC(ctx);
5149 if (unlikely(!ctx->supervisor)) {
5150 GEN_EXCP_PRIVOPC(ctx);
5153 switch (rB(ctx->opcode)) {
5157 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5158 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rS(ctx->opcode)]);
5159 gen_op_440_tlbwe(rB(ctx->opcode));
5162 GEN_EXCP_INVAL(ctx);
5169 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE)
5171 #if defined(CONFIG_USER_ONLY)
5172 GEN_EXCP_PRIVOPC(ctx);
5174 if (unlikely(!ctx->supervisor)) {
5175 GEN_EXCP_PRIVOPC(ctx);
5178 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rD(ctx->opcode)]);
5180 /* Stop translation to have a chance to raise an exception
5181 * if we just set msr_ee to 1
5188 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000EFC01, PPC_WRTEE)
5190 #if defined(CONFIG_USER_ONLY)
5191 GEN_EXCP_PRIVOPC(ctx);
5193 if (unlikely(!ctx->supervisor)) {
5194 GEN_EXCP_PRIVOPC(ctx);
5197 tcg_gen_movi_tl(cpu_T[0], ctx->opcode & 0x00010000);
5199 /* Stop translation to have a chance to raise an exception
5200 * if we just set msr_ee to 1
5206 /* PowerPC 440 specific instructions */
5208 GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC)
5210 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rS(ctx->opcode)]);
5211 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5213 tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], cpu_T[0]);
5214 gen_op_store_xer_bc();
5215 if (Rc(ctx->opcode)) {
5216 gen_op_440_dlmzb_update_Rc();
5217 gen_op_store_T0_crf(0);
5221 /* mbar replaces eieio on 440 */
5222 GEN_HANDLER(mbar, 0x1F, 0x16, 0x13, 0x001FF801, PPC_BOOKE)
5224 /* interpreted as no-op */
5227 /* msync replaces sync on 440 */
5228 GEN_HANDLER(msync, 0x1F, 0x16, 0x12, 0x03FFF801, PPC_BOOKE)
5230 /* interpreted as no-op */
5234 GEN_HANDLER2(icbt_440, "icbt", 0x1F, 0x16, 0x00, 0x03E00001, PPC_BOOKE)
5236 /* interpreted as no-op */
5237 /* XXX: specification say this is treated as a load by the MMU
5238 * but does not generate any exception
5242 /*** Altivec vector extension ***/
5243 /* Altivec registers moves */
5244 GEN32(gen_op_load_avr_A0, gen_op_load_avr_A0_avr);
5245 GEN32(gen_op_load_avr_A1, gen_op_load_avr_A1_avr);
5246 GEN32(gen_op_load_avr_A2, gen_op_load_avr_A2_avr);
5248 GEN32(gen_op_store_A0_avr, gen_op_store_A0_avr_avr);
5249 GEN32(gen_op_store_A1_avr, gen_op_store_A1_avr_avr);
5251 GEN32(gen_op_store_A2_avr, gen_op_store_A2_avr_avr);
5254 #define op_vr_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5255 #define OP_VR_LD_TABLE(name) \
5256 static GenOpFunc *gen_op_vr_l##name[NB_MEM_FUNCS] = { \
5257 GEN_MEM_FUNCS(vr_l##name), \
5259 #define OP_VR_ST_TABLE(name) \
5260 static GenOpFunc *gen_op_vr_st##name[NB_MEM_FUNCS] = { \
5261 GEN_MEM_FUNCS(vr_st##name), \
5264 #define GEN_VR_LDX(name, opc2, opc3) \
5265 GEN_HANDLER(l##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5267 if (unlikely(!ctx->altivec_enabled)) { \
5268 GEN_EXCP_NO_VR(ctx); \
5271 gen_addr_reg_index(ctx); \
5272 op_vr_ldst(vr_l##name); \
5273 gen_op_store_A0_avr(rD(ctx->opcode)); \
5276 #define GEN_VR_STX(name, opc2, opc3) \
5277 GEN_HANDLER(st##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
5279 if (unlikely(!ctx->altivec_enabled)) { \
5280 GEN_EXCP_NO_VR(ctx); \
5283 gen_addr_reg_index(ctx); \
5284 gen_op_load_avr_A0(rS(ctx->opcode)); \
5285 op_vr_ldst(vr_st##name); \
5289 GEN_VR_LDX(vx, 0x07, 0x03);
5290 /* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
5291 #define gen_op_vr_lvxl gen_op_vr_lvx
5292 GEN_VR_LDX(vxl, 0x07, 0x0B);
5295 GEN_VR_STX(vx, 0x07, 0x07);
5296 /* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
5297 #define gen_op_vr_stvxl gen_op_vr_stvx
5298 GEN_VR_STX(vxl, 0x07, 0x0F);
5300 /*** SPE extension ***/
5301 /* Register moves */
5303 static always_inline void gen_load_gpr64(TCGv t, int reg) {
5304 #if defined(TARGET_PPC64)
5305 tcg_gen_mov_i64(t, cpu_gpr[reg]);
5307 tcg_gen_extu_i32_i64(t, cpu_gprh[reg]);
5308 tcg_gen_shli_i64(t, t, 32);
5309 TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
5310 tcg_gen_extu_i32_i64(tmp, cpu_gpr[reg]);
5311 tcg_gen_or_i64(t, t, tmp);
5316 static always_inline void gen_store_gpr64(int reg, TCGv t) {
5317 #if defined(TARGET_PPC64)
5318 tcg_gen_mov_i64(cpu_gpr[reg], t);
5320 tcg_gen_trunc_i64_i32(cpu_gpr[reg], t);
5321 TCGv tmp = tcg_temp_local_new(TCG_TYPE_I64);
5322 tcg_gen_shri_i64(tmp, t, 32);
5323 tcg_gen_trunc_i64_i32(cpu_gprh[reg], tmp);
5328 #define GEN_SPE(name0, name1, opc2, opc3, inval, type) \
5329 GEN_HANDLER(name0##_##name1, 0x04, opc2, opc3, inval, type) \
5331 if (Rc(ctx->opcode)) \
5337 /* Handler for undefined SPE opcodes */
5338 static always_inline void gen_speundef (DisasContext *ctx)
5340 GEN_EXCP_INVAL(ctx);
5343 /* SPE load and stores */
5344 static always_inline void gen_addr_spe_imm_index (DisasContext *ctx, int sh)
5346 target_long simm = rB(ctx->opcode);
5348 if (rA(ctx->opcode) == 0) {
5349 tcg_gen_movi_tl(cpu_T[0], simm << sh);
5351 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5352 if (likely(simm != 0))
5353 gen_op_addi(simm << sh);
5357 #define op_spe_ldst(name) (*gen_op_##name[ctx->mem_idx])()
5358 #define OP_SPE_LD_TABLE(name) \
5359 static GenOpFunc *gen_op_spe_l##name[NB_MEM_FUNCS] = { \
5360 GEN_MEM_FUNCS(spe_l##name), \
5362 #define OP_SPE_ST_TABLE(name) \
5363 static GenOpFunc *gen_op_spe_st##name[NB_MEM_FUNCS] = { \
5364 GEN_MEM_FUNCS(spe_st##name), \
5367 #define GEN_SPE_LD(name, sh) \
5368 static always_inline void gen_evl##name (DisasContext *ctx) \
5370 if (unlikely(!ctx->spe_enabled)) { \
5371 GEN_EXCP_NO_AP(ctx); \
5374 gen_addr_spe_imm_index(ctx, sh); \
5375 op_spe_ldst(spe_l##name); \
5376 gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
5379 #define GEN_SPE_LDX(name) \
5380 static always_inline void gen_evl##name##x (DisasContext *ctx) \
5382 if (unlikely(!ctx->spe_enabled)) { \
5383 GEN_EXCP_NO_AP(ctx); \
5386 gen_addr_reg_index(ctx); \
5387 op_spe_ldst(spe_l##name); \
5388 gen_store_gpr64(rD(ctx->opcode), cpu_T64[1]); \
5391 #define GEN_SPEOP_LD(name, sh) \
5392 OP_SPE_LD_TABLE(name); \
5393 GEN_SPE_LD(name, sh); \
5396 #define GEN_SPE_ST(name, sh) \
5397 static always_inline void gen_evst##name (DisasContext *ctx) \
5399 if (unlikely(!ctx->spe_enabled)) { \
5400 GEN_EXCP_NO_AP(ctx); \
5403 gen_addr_spe_imm_index(ctx, sh); \
5404 gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
5405 op_spe_ldst(spe_st##name); \
5408 #define GEN_SPE_STX(name) \
5409 static always_inline void gen_evst##name##x (DisasContext *ctx) \
5411 if (unlikely(!ctx->spe_enabled)) { \
5412 GEN_EXCP_NO_AP(ctx); \
5415 gen_addr_reg_index(ctx); \
5416 gen_load_gpr64(cpu_T64[1], rS(ctx->opcode)); \
5417 op_spe_ldst(spe_st##name); \
5420 #define GEN_SPEOP_ST(name, sh) \
5421 OP_SPE_ST_TABLE(name); \
5422 GEN_SPE_ST(name, sh); \
5425 #define GEN_SPEOP_LDST(name, sh) \
5426 GEN_SPEOP_LD(name, sh); \
5427 GEN_SPEOP_ST(name, sh)
5429 /* SPE arithmetic and logic */
5430 #define GEN_SPEOP_ARITH2(name) \
5431 static always_inline void gen_##name (DisasContext *ctx) \
5433 if (unlikely(!ctx->spe_enabled)) { \
5434 GEN_EXCP_NO_AP(ctx); \
5437 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5438 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
5440 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5443 #define GEN_SPEOP_ARITH1(name) \
5444 static always_inline void gen_##name (DisasContext *ctx) \
5446 if (unlikely(!ctx->spe_enabled)) { \
5447 GEN_EXCP_NO_AP(ctx); \
5450 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5452 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5455 #define GEN_SPEOP_COMP(name) \
5456 static always_inline void gen_##name (DisasContext *ctx) \
5458 if (unlikely(!ctx->spe_enabled)) { \
5459 GEN_EXCP_NO_AP(ctx); \
5462 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5463 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode)); \
5465 gen_op_store_T0_crf(crfD(ctx->opcode)); \
5469 GEN_SPEOP_ARITH2(evand);
5470 GEN_SPEOP_ARITH2(evandc);
5471 GEN_SPEOP_ARITH2(evxor);
5472 GEN_SPEOP_ARITH2(evor);
5473 GEN_SPEOP_ARITH2(evnor);
5474 GEN_SPEOP_ARITH2(eveqv);
5475 GEN_SPEOP_ARITH2(evorc);
5476 GEN_SPEOP_ARITH2(evnand);
5477 GEN_SPEOP_ARITH2(evsrwu);
5478 GEN_SPEOP_ARITH2(evsrws);
5479 GEN_SPEOP_ARITH2(evslw);
5480 GEN_SPEOP_ARITH2(evrlw);
5481 GEN_SPEOP_ARITH2(evmergehi);
5482 GEN_SPEOP_ARITH2(evmergelo);
5483 GEN_SPEOP_ARITH2(evmergehilo);
5484 GEN_SPEOP_ARITH2(evmergelohi);
5487 GEN_SPEOP_ARITH2(evaddw);
5488 GEN_SPEOP_ARITH2(evsubfw);
5489 GEN_SPEOP_ARITH1(evabs);
5490 GEN_SPEOP_ARITH1(evneg);
5491 GEN_SPEOP_ARITH1(evextsb);
5492 GEN_SPEOP_ARITH1(evextsh);
5493 GEN_SPEOP_ARITH1(evrndw);
5494 GEN_SPEOP_ARITH1(evcntlzw);
5495 GEN_SPEOP_ARITH1(evcntlsw);
5496 static always_inline void gen_brinc (DisasContext *ctx)
5498 /* Note: brinc is usable even if SPE is disabled */
5499 tcg_gen_mov_tl(cpu_T[0], cpu_gpr[rA(ctx->opcode)]);
5500 tcg_gen_mov_tl(cpu_T[1], cpu_gpr[rB(ctx->opcode)]);
5502 tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_T[0]);
5505 #define GEN_SPEOP_ARITH_IMM2(name) \
5506 static always_inline void gen_##name##i (DisasContext *ctx) \
5508 if (unlikely(!ctx->spe_enabled)) { \
5509 GEN_EXCP_NO_AP(ctx); \
5512 gen_load_gpr64(cpu_T64[0], rB(ctx->opcode)); \
5513 gen_op_splatwi_T1_64(rA(ctx->opcode)); \
5515 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5518 #define GEN_SPEOP_LOGIC_IMM2(name) \
5519 static always_inline void gen_##name##i (DisasContext *ctx) \
5521 if (unlikely(!ctx->spe_enabled)) { \
5522 GEN_EXCP_NO_AP(ctx); \
5525 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode)); \
5526 gen_op_splatwi_T1_64(rB(ctx->opcode)); \
5528 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5531 GEN_SPEOP_ARITH_IMM2(evaddw);
5532 #define gen_evaddiw gen_evaddwi
5533 GEN_SPEOP_ARITH_IMM2(evsubfw);
5534 #define gen_evsubifw gen_evsubfwi
5535 GEN_SPEOP_LOGIC_IMM2(evslw);
5536 GEN_SPEOP_LOGIC_IMM2(evsrwu);
5537 #define gen_evsrwis gen_evsrwsi
5538 GEN_SPEOP_LOGIC_IMM2(evsrws);
5539 #define gen_evsrwiu gen_evsrwui
5540 GEN_SPEOP_LOGIC_IMM2(evrlw);
5542 static always_inline void gen_evsplati (DisasContext *ctx)
5544 int32_t imm = (int32_t)(rA(ctx->opcode) << 27) >> 27;
5546 gen_op_splatwi_T0_64(imm);
5547 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5550 static always_inline void gen_evsplatfi (DisasContext *ctx)
5552 uint32_t imm = rA(ctx->opcode) << 27;
5554 gen_op_splatwi_T0_64(imm);
5555 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5559 GEN_SPEOP_COMP(evcmpgtu);
5560 GEN_SPEOP_COMP(evcmpgts);
5561 GEN_SPEOP_COMP(evcmpltu);
5562 GEN_SPEOP_COMP(evcmplts);
5563 GEN_SPEOP_COMP(evcmpeq);
5565 GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, PPC_SPE); ////
5566 GEN_SPE(evaddiw, speundef, 0x01, 0x08, 0x00000000, PPC_SPE);
5567 GEN_SPE(evsubfw, speundef, 0x02, 0x08, 0x00000000, PPC_SPE); ////
5568 GEN_SPE(evsubifw, speundef, 0x03, 0x08, 0x00000000, PPC_SPE);
5569 GEN_SPE(evabs, evneg, 0x04, 0x08, 0x0000F800, PPC_SPE); ////
5570 GEN_SPE(evextsb, evextsh, 0x05, 0x08, 0x0000F800, PPC_SPE); ////
5571 GEN_SPE(evrndw, evcntlzw, 0x06, 0x08, 0x0000F800, PPC_SPE); ////
5572 GEN_SPE(evcntlsw, brinc, 0x07, 0x08, 0x00000000, PPC_SPE); //
5573 GEN_SPE(speundef, evand, 0x08, 0x08, 0x00000000, PPC_SPE); ////
5574 GEN_SPE(evandc, speundef, 0x09, 0x08, 0x00000000, PPC_SPE); ////
5575 GEN_SPE(evxor, evor, 0x0B, 0x08, 0x00000000, PPC_SPE); ////
5576 GEN_SPE(evnor, eveqv, 0x0C, 0x08, 0x00000000, PPC_SPE); ////
5577 GEN_SPE(speundef, evorc, 0x0D, 0x08, 0x00000000, PPC_SPE); ////
5578 GEN_SPE(evnand, speundef, 0x0F, 0x08, 0x00000000, PPC_SPE); ////
5579 GEN_SPE(evsrwu, evsrws, 0x10, 0x08, 0x00000000, PPC_SPE); ////
5580 GEN_SPE(evsrwiu, evsrwis, 0x11, 0x08, 0x00000000, PPC_SPE);
5581 GEN_SPE(evslw, speundef, 0x12, 0x08, 0x00000000, PPC_SPE); ////
5582 GEN_SPE(evslwi, speundef, 0x13, 0x08, 0x00000000, PPC_SPE);
5583 GEN_SPE(evrlw, evsplati, 0x14, 0x08, 0x00000000, PPC_SPE); //
5584 GEN_SPE(evrlwi, evsplatfi, 0x15, 0x08, 0x00000000, PPC_SPE);
5585 GEN_SPE(evmergehi, evmergelo, 0x16, 0x08, 0x00000000, PPC_SPE); ////
5586 GEN_SPE(evmergehilo, evmergelohi, 0x17, 0x08, 0x00000000, PPC_SPE); ////
5587 GEN_SPE(evcmpgtu, evcmpgts, 0x18, 0x08, 0x00600000, PPC_SPE); ////
5588 GEN_SPE(evcmpltu, evcmplts, 0x19, 0x08, 0x00600000, PPC_SPE); ////
5589 GEN_SPE(evcmpeq, speundef, 0x1A, 0x08, 0x00600000, PPC_SPE); ////
5591 static always_inline void gen_evsel (DisasContext *ctx)
5593 if (unlikely(!ctx->spe_enabled)) {
5594 GEN_EXCP_NO_AP(ctx);
5597 gen_op_load_crf_T0(ctx->opcode & 0x7);
5598 gen_load_gpr64(cpu_T64[0], rA(ctx->opcode));
5599 gen_load_gpr64(cpu_T64[1], rB(ctx->opcode));
5601 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]);
5604 GEN_HANDLER2(evsel0, "evsel", 0x04, 0x1c, 0x09, 0x00000000, PPC_SPE)
5608 GEN_HANDLER2(evsel1, "evsel", 0x04, 0x1d, 0x09, 0x00000000, PPC_SPE)
5612 GEN_HANDLER2(evsel2, "evsel", 0x04, 0x1e, 0x09, 0x00000000, PPC_SPE)
5616 GEN_HANDLER2(evsel3, "evsel", 0x04, 0x1f, 0x09, 0x00000000, PPC_SPE)
5621 /* Load and stores */
5622 #if defined(TARGET_PPC64)
5623 /* In that case, we already have 64 bits load & stores
5624 * so, spe_ldd is equivalent to ld and spe_std is equivalent to std
5626 #define gen_op_spe_ldd_raw gen_op_ld_raw
5627 #define gen_op_spe_ldd_user gen_op_ld_user
5628 #define gen_op_spe_ldd_kernel gen_op_ld_kernel
5629 #define gen_op_spe_ldd_hypv gen_op_ld_hypv
5630 #define gen_op_spe_ldd_64_raw gen_op_ld_64_raw
5631 #define gen_op_spe_ldd_64_user gen_op_ld_64_user
5632 #define gen_op_spe_ldd_64_kernel gen_op_ld_64_kernel
5633 #define gen_op_spe_ldd_64_hypv gen_op_ld_64_hypv
5634 #define gen_op_spe_ldd_le_raw gen_op_ld_le_raw
5635 #define gen_op_spe_ldd_le_user gen_op_ld_le_user
5636 #define gen_op_spe_ldd_le_kernel gen_op_ld_le_kernel
5637 #define gen_op_spe_ldd_le_hypv gen_op_ld_le_hypv
5638 #define gen_op_spe_ldd_le_64_raw gen_op_ld_le_64_raw
5639 #define gen_op_spe_ldd_le_64_user gen_op_ld_le_64_user
5640 #define gen_op_spe_ldd_le_64_kernel gen_op_ld_le_64_kernel
5641 #define gen_op_spe_ldd_le_64_hypv gen_op_ld_le_64_hypv
5642 #define gen_op_spe_stdd_raw gen_op_std_raw
5643 #define gen_op_spe_stdd_user gen_op_std_user
5644 #define gen_op_spe_stdd_kernel gen_op_std_kernel
5645 #define gen_op_spe_stdd_hypv gen_op_std_hypv
5646 #define gen_op_spe_stdd_64_raw gen_op_std_64_raw
5647 #define gen_op_spe_stdd_64_user gen_op_std_64_user
5648 #define gen_op_spe_stdd_64_kernel gen_op_std_64_kernel
5649 #define gen_op_spe_stdd_64_hypv gen_op_std_64_hypv
5650 #define gen_op_spe_stdd_le_raw gen_op_std_le_raw
5651 #define gen_op_spe_stdd_le_user gen_op_std_le_user
5652 #define gen_op_spe_stdd_le_kernel gen_op_std_le_kernel
5653 #define gen_op_spe_stdd_le_hypv gen_op_std_le_hypv
5654 #define gen_op_spe_stdd_le_64_raw gen_op_std_le_64_raw
5655 #define gen_op_spe_stdd_le_64_user gen_op_std_le_64_user
5656 #define gen_op_spe_stdd_le_64_kernel gen_op_std_le_64_kernel
5657 #define gen_op_spe_stdd_le_64_hypv gen_op_std_le_64_hypv
5658 #endif /* defined(TARGET_PPC64) */
5659 GEN_SPEOP_LDST(dd, 3);
5660 GEN_SPEOP_LDST(dw, 3);
5661 GEN_SPEOP_LDST(dh, 3);
5662 GEN_SPEOP_LDST(whe, 2);
5663 GEN_SPEOP_LD(whou, 2);
5664 GEN_SPEOP_LD(whos, 2);
5665 GEN_SPEOP_ST(who, 2);
5667 #if defined(TARGET_PPC64)
5668 /* In that case, spe_stwwo is equivalent to stw */
5669 #define gen_op_spe_stwwo_raw gen_op_stw_raw
5670 #define gen_op_spe_stwwo_user gen_op_stw_user
5671 #define gen_op_spe_stwwo_kernel gen_op_stw_kernel
5672 #define gen_op_spe_stwwo_hypv gen_op_stw_hypv
5673 #define gen_op_spe_stwwo_le_raw gen_op_stw_le_raw
5674 #define gen_op_spe_stwwo_le_user gen_op_stw_le_user
5675 #define gen_op_spe_stwwo_le_kernel gen_op_stw_le_kernel
5676 #define gen_op_spe_stwwo_le_hypv gen_op_stw_le_hypv
5677 #define gen_op_spe_stwwo_64_raw gen_op_stw_64_raw
5678 #define gen_op_spe_stwwo_64_user gen_op_stw_64_user
5679 #define gen_op_spe_stwwo_64_kernel gen_op_stw_64_kernel
5680 #define gen_op_spe_stwwo_64_hypv gen_op_stw_64_hypv
5681 #define gen_op_spe_stwwo_le_64_raw gen_op_stw_le_64_raw
5682 #define gen_op_spe_stwwo_le_64_user gen_op_stw_le_64_user
5683 #define gen_op_spe_stwwo_le_64_kernel gen_op_stw_le_64_kernel
5684 #define gen_op_spe_stwwo_le_64_hypv gen_op_stw_le_64_hypv
5686 #define _GEN_OP_SPE_STWWE(suffix) \
5687 static always_inline void gen_op_spe_stwwe_##suffix (void) \
5689 gen_op_srli32_T1_64(); \
5690 gen_op_spe_stwwo_##suffix(); \
5692 #define _GEN_OP_SPE_STWWE_LE(suffix) \
5693 static always_inline void gen_op_spe_stwwe_le_##suffix (void) \
5695 gen_op_srli32_T1_64(); \
5696 gen_op_spe_stwwo_le_##suffix(); \
5698 #if defined(TARGET_PPC64)
5699 #define GEN_OP_SPE_STWWE(suffix) \
5700 _GEN_OP_SPE_STWWE(suffix); \
5701 _GEN_OP_SPE_STWWE_LE(suffix); \
5702 static always_inline void gen_op_spe_stwwe_64_##suffix (void) \
5704 gen_op_srli32_T1_64(); \
5705 gen_op_spe_stwwo_64_##suffix(); \
5707 static always_inline void gen_op_spe_stwwe_le_64_##suffix (void) \
5709 gen_op_srli32_T1_64(); \
5710 gen_op_spe_stwwo_le_64_##suffix(); \
5713 #define GEN_OP_SPE_STWWE(suffix) \
5714 _GEN_OP_SPE_STWWE(suffix); \
5715 _GEN_OP_SPE_STWWE_LE(suffix)
5717 #if defined(CONFIG_USER_ONLY)
5718 GEN_OP_SPE_STWWE(raw);
5719 #else /* defined(CONFIG_USER_ONLY) */
5720 GEN_OP_SPE_STWWE(user);
5721 GEN_OP_SPE_STWWE(kernel);
5722 GEN_OP_SPE_STWWE(hypv);
5723 #endif /* defined(CONFIG_USER_ONLY) */
5724 GEN_SPEOP_ST(wwe, 2);
5725 GEN_SPEOP_ST(wwo, 2);
5727 #define GEN_SPE_LDSPLAT(name, op, suffix) \
5728 static always_inline void gen_op_spe_l##name##_##suffix (void) \
5730 gen_op_##op##_##suffix(); \
5731 gen_op_splatw_T1_64(); \
5734 #define GEN_OP_SPE_LHE(suffix) \
5735 static always_inline void gen_op_spe_lhe_##suffix (void) \
5737 gen_op_spe_lh_##suffix(); \
5738 gen_op_sli16_T1_64(); \
5741 #define GEN_OP_SPE_LHX(suffix) \
5742 static always_inline void gen_op_spe_lhx_##suffix (void) \
5744 gen_op_spe_lh_##suffix(); \
5745 gen_op_extsh_T1_64(); \
5748 #if defined(CONFIG_USER_ONLY)
5749 GEN_OP_SPE_LHE(raw);
5750 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, raw);
5751 GEN_OP_SPE_LHE(le_raw);
5752 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_raw);
5753 GEN_SPE_LDSPLAT(hhousplat, spe_lh, raw);
5754 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_raw);
5755 GEN_OP_SPE_LHX(raw);
5756 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, raw);
5757 GEN_OP_SPE_LHX(le_raw);
5758 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_raw);
5759 #if defined(TARGET_PPC64)
5760 GEN_OP_SPE_LHE(64_raw);
5761 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_raw);
5762 GEN_OP_SPE_LHE(le_64_raw);
5763 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_raw);
5764 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_raw);
5765 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_raw);
5766 GEN_OP_SPE_LHX(64_raw);
5767 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_raw);
5768 GEN_OP_SPE_LHX(le_64_raw);
5769 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_raw);
5772 GEN_OP_SPE_LHE(user);
5773 GEN_OP_SPE_LHE(kernel);
5774 GEN_OP_SPE_LHE(hypv);
5775 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, user);
5776 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, kernel);
5777 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, hypv);
5778 GEN_OP_SPE_LHE(le_user);
5779 GEN_OP_SPE_LHE(le_kernel);
5780 GEN_OP_SPE_LHE(le_hypv);
5781 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_user);
5782 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_kernel);
5783 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_hypv);
5784 GEN_SPE_LDSPLAT(hhousplat, spe_lh, user);
5785 GEN_SPE_LDSPLAT(hhousplat, spe_lh, kernel);
5786 GEN_SPE_LDSPLAT(hhousplat, spe_lh, hypv);
5787 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_user);
5788 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_kernel);
5789 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_hypv);
5790 GEN_OP_SPE_LHX(user);
5791 GEN_OP_SPE_LHX(kernel);
5792 GEN_OP_SPE_LHX(hypv);
5793 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, user);
5794 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, kernel);
5795 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, hypv);
5796 GEN_OP_SPE_LHX(le_user);
5797 GEN_OP_SPE_LHX(le_kernel);
5798 GEN_OP_SPE_LHX(le_hypv);
5799 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_user);
5800 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_kernel);
5801 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_hypv);
5802 #if defined(TARGET_PPC64)
5803 GEN_OP_SPE_LHE(64_user);
5804 GEN_OP_SPE_LHE(64_kernel);
5805 GEN_OP_SPE_LHE(64_hypv);
5806 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_user);
5807 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_kernel);
5808 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, 64_hypv);
5809 GEN_OP_SPE_LHE(le_64_user);
5810 GEN_OP_SPE_LHE(le_64_kernel);
5811 GEN_OP_SPE_LHE(le_64_hypv);
5812 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_user);
5813 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_kernel);
5814 GEN_SPE_LDSPLAT(hhesplat, spe_lhe, le_64_hypv);
5815 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_user);
5816 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_kernel);
5817 GEN_SPE_LDSPLAT(hhousplat, spe_lh, 64_hypv);
5818 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_user);
5819 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_kernel);
5820 GEN_SPE_LDSPLAT(hhousplat, spe_lh, le_64_hypv);
5821 GEN_OP_SPE_LHX(64_user);
5822 GEN_OP_SPE_LHX(64_kernel);
5823 GEN_OP_SPE_LHX(64_hypv);
5824 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_user);
5825 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_kernel);
5826 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, 64_hypv);
5827 GEN_OP_SPE_LHX(le_64_user);
5828 GEN_OP_SPE_LHX(le_64_kernel);
5829 GEN_OP_SPE_LHX(le_64_hypv);
5830 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_user);
5831 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_kernel);
5832 GEN_SPE_LDSPLAT(hhossplat, spe_lhx, le_64_hypv);
5835 GEN_SPEOP_LD(hhesplat, 1);
5836 GEN_SPEOP_LD(hhousplat, 1);
5837 GEN_SPEOP_LD(hhossplat, 1);
5838 GEN_SPEOP_LD(wwsplat, 2);
5839 GEN_SPEOP_LD(whsplat, 2);
5841 GEN_SPE(evlddx, evldd, 0x00, 0x0C, 0x00000000, PPC_SPE); //
5842 GEN_SPE(evldwx, evldw, 0x01, 0x0C, 0x00000000, PPC_SPE); //
5843 GEN_SPE(evldhx, evldh, 0x02, 0x0C, 0x00000000, PPC_SPE); //
5844 GEN_SPE(evlhhesplatx, evlhhesplat, 0x04, 0x0C, 0x00000000, PPC_SPE); //
5845 GEN_SPE(evlhhousplatx, evlhhousplat, 0x06, 0x0C, 0x00000000, PPC_SPE); //
5846 GEN_SPE(evlhhossplatx, evlhhossplat, 0x07, 0x0C, 0x00000000, PPC_SPE); //
5847 GEN_SPE(evlwhex, evlwhe, 0x08, 0x0C, 0x00000000, PPC_SPE); //
5848 GEN_SPE(evlwhoux, evlwhou, 0x0A, 0x0C, 0x00000000, PPC_SPE); //
5849 GEN_SPE(evlwhosx, evlwhos, 0x0B, 0x0C, 0x00000000, PPC_SPE); //
5850 GEN_SPE(evlwwsplatx, evlwwsplat, 0x0C, 0x0C, 0x00000000, PPC_SPE); //
5851 GEN_SPE(evlwhsplatx, evlwhsplat, 0x0E, 0x0C, 0x00000000, PPC_SPE); //
5852 GEN_SPE(evstddx, evstdd, 0x10, 0x0C, 0x00000000, PPC_SPE); //
5853 GEN_SPE(evstdwx, evstdw, 0x11, 0x0C, 0x00000000, PPC_SPE); //
5854 GEN_SPE(evstdhx, evstdh, 0x12, 0x0C, 0x00000000, PPC_SPE); //
5855 GEN_SPE(evstwhex, evstwhe, 0x18, 0x0C, 0x00000000, PPC_SPE); //
5856 GEN_SPE(evstwhox, evstwho, 0x1A, 0x0C, 0x00000000, PPC_SPE); //
5857 GEN_SPE(evstwwex, evstwwe, 0x1C, 0x0C, 0x00000000, PPC_SPE); //
5858 GEN_SPE(evstwwox, evstwwo, 0x1E, 0x0C, 0x00000000, PPC_SPE); //
5860 /* Multiply and add - TODO */
5862 GEN_SPE(speundef, evmhessf, 0x01, 0x10, 0x00000000, PPC_SPE);
5863 GEN_SPE(speundef, evmhossf, 0x03, 0x10, 0x00000000, PPC_SPE);
5864 GEN_SPE(evmheumi, evmhesmi, 0x04, 0x10, 0x00000000, PPC_SPE);
5865 GEN_SPE(speundef, evmhesmf, 0x05, 0x10, 0x00000000, PPC_SPE);
5866 GEN_SPE(evmhoumi, evmhosmi, 0x06, 0x10, 0x00000000, PPC_SPE);
5867 GEN_SPE(speundef, evmhosmf, 0x07, 0x10, 0x00000000, PPC_SPE);
5868 GEN_SPE(speundef, evmhessfa, 0x11, 0x10, 0x00000000, PPC_SPE);
5869 GEN_SPE(speundef, evmhossfa, 0x13, 0x10, 0x00000000, PPC_SPE);
5870 GEN_SPE(evmheumia, evmhesmia, 0x14, 0x10, 0x00000000, PPC_SPE);
5871 GEN_SPE(speundef, evmhesmfa, 0x15, 0x10, 0x00000000, PPC_SPE);
5872 GEN_SPE(evmhoumia, evmhosmia, 0x16, 0x10, 0x00000000, PPC_SPE);
5873 GEN_SPE(speundef, evmhosmfa, 0x17, 0x10, 0x00000000, PPC_SPE);
5875 GEN_SPE(speundef, evmwhssf, 0x03, 0x11, 0x00000000, PPC_SPE);
5876 GEN_SPE(evmwlumi, speundef, 0x04, 0x11, 0x00000000, PPC_SPE);
5877 GEN_SPE(evmwhumi, evmwhsmi, 0x06, 0x11, 0x00000000, PPC_SPE);
5878 GEN_SPE(speundef, evmwhsmf, 0x07, 0x11, 0x00000000, PPC_SPE);
5879 GEN_SPE(speundef, evmwssf, 0x09, 0x11, 0x00000000, PPC_SPE);
5880 GEN_SPE(evmwumi, evmwsmi, 0x0C, 0x11, 0x00000000, PPC_SPE);
5881 GEN_SPE(speundef, evmwsmf, 0x0D, 0x11, 0x00000000, PPC_SPE);
5882 GEN_SPE(speundef, evmwhssfa, 0x13, 0x11, 0x00000000, PPC_SPE);
5883 GEN_SPE(evmwlumia, speundef, 0x14, 0x11, 0x00000000, PPC_SPE);
5884 GEN_SPE(evmwhumia, evmwhsmia, 0x16, 0x11, 0x00000000, PPC_SPE);
5885 GEN_SPE(speundef, evmwhsmfa, 0x17, 0x11, 0x00000000, PPC_SPE);
5886 GEN_SPE(speundef, evmwssfa, 0x19, 0x11, 0x00000000, PPC_SPE);
5887 GEN_SPE(evmwumia, evmwsmia, 0x1C, 0x11, 0x00000000, PPC_SPE);
5888 GEN_SPE(speundef, evmwsmfa, 0x1D, 0x11, 0x00000000, PPC_SPE);
5890 GEN_SPE(evadduiaaw, evaddsiaaw, 0x00, 0x13, 0x0000F800, PPC_SPE);
5891 GEN_SPE(evsubfusiaaw, evsubfssiaaw, 0x01, 0x13, 0x0000F800, PPC_SPE);
5892 GEN_SPE(evaddumiaaw, evaddsmiaaw, 0x04, 0x13, 0x0000F800, PPC_SPE);
5893 GEN_SPE(evsubfumiaaw, evsubfsmiaaw, 0x05, 0x13, 0x0000F800, PPC_SPE);
5894 GEN_SPE(evdivws, evdivwu, 0x06, 0x13, 0x00000000, PPC_SPE);
5895 GEN_SPE(evmra, speundef, 0x07, 0x13, 0x0000F800, PPC_SPE);
5897 GEN_SPE(evmheusiaaw, evmhessiaaw, 0x00, 0x14, 0x00000000, PPC_SPE);
5898 GEN_SPE(speundef, evmhessfaaw, 0x01, 0x14, 0x00000000, PPC_SPE);
5899 GEN_SPE(evmhousiaaw, evmhossiaaw, 0x02, 0x14, 0x00000000, PPC_SPE);
5900 GEN_SPE(speundef, evmhossfaaw, 0x03, 0x14, 0x00000000, PPC_SPE);
5901 GEN_SPE(evmheumiaaw, evmhesmiaaw, 0x04, 0x14, 0x00000000, PPC_SPE);
5902 GEN_SPE(speundef, evmhesmfaaw, 0x05, 0x14, 0x00000000, PPC_SPE);
5903 GEN_SPE(evmhoumiaaw, evmhosmiaaw, 0x06, 0x14, 0x00000000, PPC_SPE);
5904 GEN_SPE(speundef, evmhosmfaaw, 0x07, 0x14, 0x00000000, PPC_SPE);
5905 GEN_SPE(evmhegumiaa, evmhegsmiaa, 0x14, 0x14, 0x00000000, PPC_SPE);
5906 GEN_SPE(speundef, evmhegsmfaa, 0x15, 0x14, 0x00000000, PPC_SPE);
5907 GEN_SPE(evmhogumiaa, evmhogsmiaa, 0x16, 0x14, 0x00000000, PPC_SPE);
5908 GEN_SPE(speundef, evmhogsmfaa, 0x17, 0x14, 0x00000000, PPC_SPE);
5910 GEN_SPE(evmwlusiaaw, evmwlssiaaw, 0x00, 0x15, 0x00000000, PPC_SPE);
5911 GEN_SPE(evmwlumiaaw, evmwlsmiaaw, 0x04, 0x15, 0x00000000, PPC_SPE);
5912 GEN_SPE(speundef, evmwssfaa, 0x09, 0x15, 0x00000000, PPC_SPE);
5913 GEN_SPE(evmwumiaa, evmwsmiaa, 0x0C, 0x15, 0x00000000, PPC_SPE);
5914 GEN_SPE(speundef, evmwsmfaa, 0x0D, 0x15, 0x00000000, PPC_SPE);
5916 GEN_SPE(evmheusianw, evmhessianw, 0x00, 0x16, 0x00000000, PPC_SPE);
5917 GEN_SPE(speundef, evmhessfanw, 0x01, 0x16, 0x00000000, PPC_SPE);
5918 GEN_SPE(evmhousianw, evmhossianw, 0x02, 0x16, 0x00000000, PPC_SPE);
5919 GEN_SPE(speundef, evmhossfanw, 0x03, 0x16, 0x00000000, PPC_SPE);
5920 GEN_SPE(evmheumianw, evmhesmianw, 0x04, 0x16, 0x00000000, PPC_SPE);
5921 GEN_SPE(speundef, evmhesmfanw, 0x05, 0x16, 0x00000000, PPC_SPE);
5922 GEN_SPE(evmhoumianw, evmhosmianw, 0x06, 0x16, 0x00000000, PPC_SPE);
5923 GEN_SPE(speundef, evmhosmfanw, 0x07, 0x16, 0x00000000, PPC_SPE);
5924 GEN_SPE(evmhegumian, evmhegsmian, 0x14, 0x16, 0x00000000, PPC_SPE);
5925 GEN_SPE(speundef, evmhegsmfan, 0x15, 0x16, 0x00000000, PPC_SPE);
5926 GEN_SPE(evmhigumian, evmhigsmian, 0x16, 0x16, 0x00000000, PPC_SPE);
5927 GEN_SPE(speundef, evmhogsmfan, 0x17, 0x16, 0x00000000, PPC_SPE);
5929 GEN_SPE(evmwlusianw, evmwlssianw, 0x00, 0x17, 0x00000000, PPC_SPE);
5930 GEN_SPE(evmwlumianw, evmwlsmianw, 0x04, 0x17, 0x00000000, PPC_SPE);
5931 GEN_SPE(speundef, evmwssfan, 0x09, 0x17, 0x00000000, PPC_SPE);
5932 GEN_SPE(evmwumian, evmwsmian, 0x0C, 0x17, 0x00000000, PPC_SPE);
5933 GEN_SPE(speundef, evmwsmfan, 0x0D, 0x17, 0x00000000, PPC_SPE);
5936 /*** SPE floating-point extension ***/
5937 #define GEN_SPEFPUOP_CONV(name) \
5938 static always_inline void gen_##name (DisasContext *ctx) \
5940 gen_load_gpr64(cpu_T64[0], rB(ctx->opcode)); \
5942 gen_store_gpr64(rD(ctx->opcode), cpu_T64[0]); \
5945 /* Single precision floating-point vectors operations */
5947 GEN_SPEOP_ARITH2(evfsadd);
5948 GEN_SPEOP_ARITH2(evfssub);
5949 GEN_SPEOP_ARITH2(evfsmul);
5950 GEN_SPEOP_ARITH2(evfsdiv);
5951 GEN_SPEOP_ARITH1(evfsabs);
5952 GEN_SPEOP_ARITH1(evfsnabs);
5953 GEN_SPEOP_ARITH1(evfsneg);
5955 GEN_SPEFPUOP_CONV(evfscfui);
5956 GEN_SPEFPUOP_CONV(evfscfsi);
5957 GEN_SPEFPUOP_CONV(evfscfuf);
5958 GEN_SPEFPUOP_CONV(evfscfsf);
5959 GEN_SPEFPUOP_CONV(evfsctui);
5960 GEN_SPEFPUOP_CONV(evfsctsi);
5961 GEN_SPEFPUOP_CONV(evfsctuf);
5962 GEN_SPEFPUOP_CONV(evfsctsf);
5963 GEN_SPEFPUOP_CONV(evfsctuiz);
5964 GEN_SPEFPUOP_CONV(evfsctsiz);
5966 GEN_SPEOP_COMP(evfscmpgt);
5967 GEN_SPEOP_COMP(evfscmplt);
5968 GEN_SPEOP_COMP(evfscmpeq);
5969 GEN_SPEOP_COMP(evfststgt);
5970 GEN_SPEOP_COMP(evfststlt);
5971 GEN_SPEOP_COMP(evfststeq);
5973 /* Opcodes definitions */
5974 GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
5975 GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
5976 GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
5977 GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
5978 GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
5979 GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
5980 GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
5981 GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
5982 GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
5983 GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
5984 GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
5985 GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
5986 GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
5987 GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
5989 /* Single precision floating-point operations */
5991 GEN_SPEOP_ARITH2(efsadd);
5992 GEN_SPEOP_ARITH2(efssub);
5993 GEN_SPEOP_ARITH2(efsmul);
5994 GEN_SPEOP_ARITH2(efsdiv);
5995 GEN_SPEOP_ARITH1(efsabs);
5996 GEN_SPEOP_ARITH1(efsnabs);
5997 GEN_SPEOP_ARITH1(efsneg);
5999 GEN_SPEFPUOP_CONV(efscfui);
6000 GEN_SPEFPUOP_CONV(efscfsi);
6001 GEN_SPEFPUOP_CONV(efscfuf);
6002 GEN_SPEFPUOP_CONV(efscfsf);
6003 GEN_SPEFPUOP_CONV(efsctui);
6004 GEN_SPEFPUOP_CONV(efsctsi);
6005 GEN_SPEFPUOP_CONV(efsctuf);
6006 GEN_SPEFPUOP_CONV(efsctsf);
6007 GEN_SPEFPUOP_CONV(efsctuiz);
6008 GEN_SPEFPUOP_CONV(efsctsiz);
6009 GEN_SPEFPUOP_CONV(efscfd);
6011 GEN_SPEOP_COMP(efscmpgt);
6012 GEN_SPEOP_COMP(efscmplt);
6013 GEN_SPEOP_COMP(efscmpeq);
6014 GEN_SPEOP_COMP(efststgt);
6015 GEN_SPEOP_COMP(efststlt);
6016 GEN_SPEOP_COMP(efststeq);
6018 /* Opcodes definitions */
6019 GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
6020 GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
6021 GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
6022 GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
6023 GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
6024 GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
6025 GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
6026 GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
6027 GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
6028 GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
6029 GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
6030 GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
6031 GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
6032 GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
6034 /* Double precision floating-point operations */
6036 GEN_SPEOP_ARITH2(efdadd);
6037 GEN_SPEOP_ARITH2(efdsub);
6038 GEN_SPEOP_ARITH2(efdmul);
6039 GEN_SPEOP_ARITH2(efddiv);
6040 GEN_SPEOP_ARITH1(efdabs);
6041 GEN_SPEOP_ARITH1(efdnabs);
6042 GEN_SPEOP_ARITH1(efdneg);
6045 GEN_SPEFPUOP_CONV(efdcfui);
6046 GEN_SPEFPUOP_CONV(efdcfsi);
6047 GEN_SPEFPUOP_CONV(efdcfuf);
6048 GEN_SPEFPUOP_CONV(efdcfsf);
6049 GEN_SPEFPUOP_CONV(efdctui);
6050 GEN_SPEFPUOP_CONV(efdctsi);
6051 GEN_SPEFPUOP_CONV(efdctuf);
6052 GEN_SPEFPUOP_CONV(efdctsf);
6053 GEN_SPEFPUOP_CONV(efdctuiz);
6054 GEN_SPEFPUOP_CONV(efdctsiz);
6055 GEN_SPEFPUOP_CONV(efdcfs);
6056 GEN_SPEFPUOP_CONV(efdcfuid);
6057 GEN_SPEFPUOP_CONV(efdcfsid);
6058 GEN_SPEFPUOP_CONV(efdctuidz);
6059 GEN_SPEFPUOP_CONV(efdctsidz);
6061 GEN_SPEOP_COMP(efdcmpgt);
6062 GEN_SPEOP_COMP(efdcmplt);
6063 GEN_SPEOP_COMP(efdcmpeq);
6064 GEN_SPEOP_COMP(efdtstgt);
6065 GEN_SPEOP_COMP(efdtstlt);
6066 GEN_SPEOP_COMP(efdtsteq);
6068 /* Opcodes definitions */
6069 GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
6070 GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
6071 GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
6072 GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
6073 GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
6074 GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
6075 GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
6076 GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
6077 GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
6078 GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
6079 GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
6080 GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
6081 GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
6082 GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
6083 GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
6084 GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
6086 /* End opcode list */
6087 GEN_OPCODE_MARK(end);
6089 #include "translate_init.c"
6090 #include "helper_regs.h"
6092 /*****************************************************************************/
6093 /* Misc PowerPC helpers */
6094 void cpu_dump_state (CPUState *env, FILE *f,
6095 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6103 cpu_fprintf(f, "NIP " ADDRX " LR " ADDRX " CTR " ADDRX " XER %08x\n",
6104 env->nip, env->lr, env->ctr, hreg_load_xer(env));
6105 cpu_fprintf(f, "MSR " ADDRX " HID0 " ADDRX " HF " ADDRX " idx %d\n",
6106 env->msr, env->spr[SPR_HID0], env->hflags, env->mmu_idx);
6107 #if !defined(NO_TIMER_DUMP)
6108 cpu_fprintf(f, "TB %08x %08x "
6109 #if !defined(CONFIG_USER_ONLY)
6113 cpu_ppc_load_tbu(env), cpu_ppc_load_tbl(env)
6114 #if !defined(CONFIG_USER_ONLY)
6115 , cpu_ppc_load_decr(env)
6119 for (i = 0; i < 32; i++) {
6120 if ((i & (RGPL - 1)) == 0)
6121 cpu_fprintf(f, "GPR%02d", i);
6122 cpu_fprintf(f, " " REGX, ppc_dump_gpr(env, i));
6123 if ((i & (RGPL - 1)) == (RGPL - 1))
6124 cpu_fprintf(f, "\n");
6126 cpu_fprintf(f, "CR ");
6127 for (i = 0; i < 8; i++)
6128 cpu_fprintf(f, "%01x", env->crf[i]);
6129 cpu_fprintf(f, " [");
6130 for (i = 0; i < 8; i++) {
6132 if (env->crf[i] & 0x08)
6134 else if (env->crf[i] & 0x04)
6136 else if (env->crf[i] & 0x02)
6138 cpu_fprintf(f, " %c%c", a, env->crf[i] & 0x01 ? 'O' : ' ');
6140 cpu_fprintf(f, " ] RES " ADDRX "\n", env->reserve);
6141 for (i = 0; i < 32; i++) {
6142 if ((i & (RFPL - 1)) == 0)
6143 cpu_fprintf(f, "FPR%02d", i);
6144 cpu_fprintf(f, " %016" PRIx64, *((uint64_t *)&env->fpr[i]));
6145 if ((i & (RFPL - 1)) == (RFPL - 1))
6146 cpu_fprintf(f, "\n");
6148 #if !defined(CONFIG_USER_ONLY)
6149 cpu_fprintf(f, "SRR0 " ADDRX " SRR1 " ADDRX " SDR1 " ADDRX "\n",
6150 env->spr[SPR_SRR0], env->spr[SPR_SRR1], env->sdr1);
6157 void cpu_dump_statistics (CPUState *env, FILE*f,
6158 int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
6161 #if defined(DO_PPC_STATISTICS)
6162 opc_handler_t **t1, **t2, **t3, *handler;
6166 for (op1 = 0; op1 < 64; op1++) {
6168 if (is_indirect_opcode(handler)) {
6169 t2 = ind_table(handler);
6170 for (op2 = 0; op2 < 32; op2++) {
6172 if (is_indirect_opcode(handler)) {
6173 t3 = ind_table(handler);
6174 for (op3 = 0; op3 < 32; op3++) {
6176 if (handler->count == 0)
6178 cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
6180 op1, op2, op3, op1, (op3 << 5) | op2,
6182 handler->count, handler->count);
6185 if (handler->count == 0)
6187 cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
6189 op1, op2, op1, op2, handler->oname,
6190 handler->count, handler->count);
6194 if (handler->count == 0)
6196 cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
6197 op1, op1, handler->oname,
6198 handler->count, handler->count);
6204 /*****************************************************************************/
6205 static always_inline void gen_intermediate_code_internal (CPUState *env,
6206 TranslationBlock *tb,
6209 DisasContext ctx, *ctxp = &ctx;
6210 opc_handler_t **table, *handler;
6211 target_ulong pc_start;
6212 uint16_t *gen_opc_end;
6213 int supervisor, little_endian;
6219 gen_opc_end = gen_opc_buf + OPC_MAX_SIZE;
6220 #if defined(OPTIMIZE_FPRF_UPDATE)
6221 gen_fprf_ptr = gen_fprf_buf;
6225 ctx.exception = POWERPC_EXCP_NONE;
6226 ctx.spr_cb = env->spr_cb;
6227 supervisor = env->mmu_idx;
6228 #if !defined(CONFIG_USER_ONLY)
6229 ctx.supervisor = supervisor;
6231 little_endian = env->hflags & (1 << MSR_LE) ? 1 : 0;
6232 #if defined(TARGET_PPC64)
6233 ctx.sf_mode = msr_sf;
6234 ctx.mem_idx = (supervisor << 2) | (msr_sf << 1) | little_endian;
6236 ctx.mem_idx = (supervisor << 1) | little_endian;
6238 ctx.dcache_line_size = env->dcache_line_size;
6239 ctx.fpu_enabled = msr_fp;
6240 if ((env->flags & POWERPC_FLAG_SPE) && msr_spe)
6241 ctx.spe_enabled = msr_spe;
6243 ctx.spe_enabled = 0;
6244 if ((env->flags & POWERPC_FLAG_VRE) && msr_vr)
6245 ctx.altivec_enabled = msr_vr;
6247 ctx.altivec_enabled = 0;
6248 if ((env->flags & POWERPC_FLAG_SE) && msr_se)
6249 ctx.singlestep_enabled = CPU_SINGLE_STEP;
6251 ctx.singlestep_enabled = 0;
6252 if ((env->flags & POWERPC_FLAG_BE) && msr_be)
6253 ctx.singlestep_enabled |= CPU_BRANCH_STEP;
6254 if (unlikely(env->singlestep_enabled))
6255 ctx.singlestep_enabled |= GDBSTUB_SINGLE_STEP;
6256 #if defined (DO_SINGLE_STEP) && 0
6257 /* Single step trace mode */
6261 max_insns = tb->cflags & CF_COUNT_MASK;
6263 max_insns = CF_COUNT_MASK;
6266 /* Set env in case of segfault during code fetch */
6267 while (ctx.exception == POWERPC_EXCP_NONE && gen_opc_ptr < gen_opc_end) {
6268 if (unlikely(env->nb_breakpoints > 0)) {
6269 for (j = 0; j < env->nb_breakpoints; j++) {
6270 if (env->breakpoints[j] == ctx.nip) {
6271 gen_update_nip(&ctx, ctx.nip);
6277 if (unlikely(search_pc)) {
6278 j = gen_opc_ptr - gen_opc_buf;
6282 gen_opc_instr_start[lj++] = 0;
6283 gen_opc_pc[lj] = ctx.nip;
6284 gen_opc_instr_start[lj] = 1;
6285 gen_opc_icount[lj] = num_insns;
6288 #if defined PPC_DEBUG_DISAS
6289 if (loglevel & CPU_LOG_TB_IN_ASM) {
6290 fprintf(logfile, "----------------\n");
6291 fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
6292 ctx.nip, supervisor, (int)msr_ir);
6295 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
6297 if (unlikely(little_endian)) {
6298 ctx.opcode = bswap32(ldl_code(ctx.nip));
6300 ctx.opcode = ldl_code(ctx.nip);
6302 #if defined PPC_DEBUG_DISAS
6303 if (loglevel & CPU_LOG_TB_IN_ASM) {
6304 fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
6305 ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
6306 opc3(ctx.opcode), little_endian ? "little" : "big");
6310 table = env->opcodes;
6312 handler = table[opc1(ctx.opcode)];
6313 if (is_indirect_opcode(handler)) {
6314 table = ind_table(handler);
6315 handler = table[opc2(ctx.opcode)];
6316 if (is_indirect_opcode(handler)) {
6317 table = ind_table(handler);
6318 handler = table[opc3(ctx.opcode)];
6321 /* Is opcode *REALLY* valid ? */
6322 if (unlikely(handler->handler == &gen_invalid)) {
6323 if (loglevel != 0) {
6324 fprintf(logfile, "invalid/unsupported opcode: "
6325 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6326 opc1(ctx.opcode), opc2(ctx.opcode),
6327 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6329 printf("invalid/unsupported opcode: "
6330 "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
6331 opc1(ctx.opcode), opc2(ctx.opcode),
6332 opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
6335 if (unlikely((ctx.opcode & handler->inval) != 0)) {
6336 if (loglevel != 0) {
6337 fprintf(logfile, "invalid bits: %08x for opcode: "
6338 "%02x - %02x - %02x (%08x) " ADDRX "\n",
6339 ctx.opcode & handler->inval, opc1(ctx.opcode),
6340 opc2(ctx.opcode), opc3(ctx.opcode),
6341 ctx.opcode, ctx.nip - 4);
6343 printf("invalid bits: %08x for opcode: "
6344 "%02x - %02x - %02x (%08x) " ADDRX "\n",
6345 ctx.opcode & handler->inval, opc1(ctx.opcode),
6346 opc2(ctx.opcode), opc3(ctx.opcode),
6347 ctx.opcode, ctx.nip - 4);
6349 GEN_EXCP_INVAL(ctxp);
6353 (*(handler->handler))(&ctx);
6354 #if defined(DO_PPC_STATISTICS)
6357 /* Check trace mode exceptions */
6358 if (unlikely(ctx.singlestep_enabled & CPU_SINGLE_STEP &&
6359 (ctx.nip <= 0x100 || ctx.nip > 0xF00) &&
6360 ctx.exception != POWERPC_SYSCALL &&
6361 ctx.exception != POWERPC_EXCP_TRAP &&
6362 ctx.exception != POWERPC_EXCP_BRANCH)) {
6363 GEN_EXCP(ctxp, POWERPC_EXCP_TRACE, 0);
6364 } else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
6365 (env->singlestep_enabled) ||
6366 num_insns >= max_insns)) {
6367 /* if we reach a page boundary or are single stepping, stop
6372 #if defined (DO_SINGLE_STEP)
6376 if (tb->cflags & CF_LAST_IO)
6378 if (ctx.exception == POWERPC_EXCP_NONE) {
6379 gen_goto_tb(&ctx, 0, ctx.nip);
6380 } else if (ctx.exception != POWERPC_EXCP_BRANCH) {
6381 if (unlikely(env->singlestep_enabled)) {
6382 gen_update_nip(&ctx, ctx.nip);
6385 /* Generate the return instruction */
6388 gen_icount_end(tb, num_insns);
6389 *gen_opc_ptr = INDEX_op_end;
6390 if (unlikely(search_pc)) {
6391 j = gen_opc_ptr - gen_opc_buf;
6394 gen_opc_instr_start[lj++] = 0;
6396 tb->size = ctx.nip - pc_start;
6397 tb->icount = num_insns;
6399 #if defined(DEBUG_DISAS)
6400 if (loglevel & CPU_LOG_TB_CPU) {
6401 fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
6402 cpu_dump_state(env, logfile, fprintf, 0);
6404 if (loglevel & CPU_LOG_TB_IN_ASM) {
6406 flags = env->bfd_mach;
6407 flags |= little_endian << 16;
6408 fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
6409 target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
6410 fprintf(logfile, "\n");
6415 void gen_intermediate_code (CPUState *env, struct TranslationBlock *tb)
6417 gen_intermediate_code_internal(env, tb, 0);
6420 void gen_intermediate_code_pc (CPUState *env, struct TranslationBlock *tb)
6422 gen_intermediate_code_internal(env, tb, 1);
6425 void gen_pc_load(CPUState *env, TranslationBlock *tb,
6426 unsigned long searched_pc, int pc_pos, void *puc)
6429 /* for PPC, we need to look at the micro operation to get the
6431 env->nip = gen_opc_pc[pc_pos];
6432 c = gen_opc_buf[pc_pos];
6434 #if defined(CONFIG_USER_ONLY)
6436 case INDEX_op_ ## op ## _raw
6439 case INDEX_op_ ## op ## _user:\
6440 case INDEX_op_ ## op ## _kernel:\
6441 case INDEX_op_ ## op ## _hypv
6448 type = ACCESS_FLOAT;
6464 env->access_type = type;