#include "disas.h"
#include "tcg-op.h"
#include "qemu-common.h"
+#include "host-utils.h"
#include "helper.h"
#define GEN_HELPER 1
#define GDBSTUB_SINGLE_STEP 0x4
/* Include definitions for instructions classes and implementations flags */
-//#define DO_SINGLE_STEP
//#define PPC_DEBUG_DISAS
//#define DO_PPC_STATISTICS
+#ifdef PPC_DEBUG_DISAS
+# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
+#else
+# define LOG_DISAS(...) do { } while (0)
+#endif
/*****************************************************************************/
/* Code translation helpers */
{
int i;
char* p;
+ size_t cpu_reg_names_size;
static int done_init = 0;
if (done_init)
cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
p = cpu_reg_names;
+ cpu_reg_names_size = sizeof(cpu_reg_names);
for (i = 0; i < 8; i++) {
- sprintf(p, "crf%d", i);
+ snprintf(p, cpu_reg_names_size, "crf%d", i);
cpu_crf[i] = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUState, crf[i]), p);
p += 5;
+ cpu_reg_names_size -= 5;
}
for (i = 0; i < 32; i++) {
- sprintf(p, "r%d", i);
+ snprintf(p, cpu_reg_names_size, "r%d", i);
cpu_gpr[i] = tcg_global_mem_new(TCG_AREG0,
offsetof(CPUState, gpr[i]), p);
p += (i < 10) ? 3 : 4;
+ cpu_reg_names_size -= (i < 10) ? 3 : 4;
#if !defined(TARGET_PPC64)
- sprintf(p, "r%dH", i);
+ snprintf(p, cpu_reg_names_size, "r%dH", i);
cpu_gprh[i] = tcg_global_mem_new_i32(TCG_AREG0,
offsetof(CPUState, gprh[i]), p);
p += (i < 10) ? 4 : 5;
+ cpu_reg_names_size -= (i < 10) ? 4 : 5;
#endif
- sprintf(p, "fp%d", i);
+ snprintf(p, cpu_reg_names_size, "fp%d", i);
cpu_fpr[i] = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUState, fpr[i]), p);
p += (i < 10) ? 4 : 5;
+ cpu_reg_names_size -= (i < 10) ? 4 : 5;
- sprintf(p, "avr%dH", i);
+ snprintf(p, cpu_reg_names_size, "avr%dH", i);
#ifdef WORDS_BIGENDIAN
cpu_avrh[i] = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUState, avr[i].u64[0]), p);
offsetof(CPUState, avr[i].u64[1]), p);
#endif
p += (i < 10) ? 6 : 7;
+ cpu_reg_names_size -= (i < 10) ? 6 : 7;
- sprintf(p, "avr%dL", i);
+ snprintf(p, cpu_reg_names_size, "avr%dL", i);
#ifdef WORDS_BIGENDIAN
cpu_avrl[i] = tcg_global_mem_new_i64(TCG_AREG0,
offsetof(CPUState, avr[i].u64[1]), p);
offsetof(CPUState, avr[i].u64[0]), p);
#endif
p += (i < 10) ? 6 : 7;
+ cpu_reg_names_size -= (i < 10) ? 6 : 7;
}
cpu_nip = tcg_global_mem_new(TCG_AREG0,
static always_inline void gen_debug_exception (DisasContext *ctx)
{
TCGv_i32 t0;
- gen_update_nip(ctx, ctx->nip);
+
+ if (ctx->exception != POWERPC_EXCP_BRANCH)
+ gen_update_nip(ctx, ctx->nip);
t0 = tcg_const_i32(EXCP_DEBUG);
gen_helper_raise_exception(t0);
tcg_temp_free_i32(t0);
EXTRACT_SHELPER(SIMM, 0, 16);
/* 16 bits unsigned immediate value */
EXTRACT_HELPER(UIMM, 0, 16);
+/* 5 bits signed immediate value */
+EXTRACT_HELPER(SIMM5, 16, 5);
+/* 5 bits signed immediate value */
+EXTRACT_HELPER(UIMM5, 16, 5);
/* Bit count */
EXTRACT_HELPER(NB, 11, 5);
/* Shift count */
EXTRACT_HELPER(SH, 11, 5);
+/* Vector shift count */
+EXTRACT_HELPER(VSH, 6, 4);
/* Mask start */
EXTRACT_HELPER(MB, 6, 5);
/* Mask end */
}
/*****************************************************************************/
-/* PowerPC Instructions types definitions */
-enum {
- PPC_NONE = 0x0000000000000000ULL,
- /* PowerPC base instructions set */
- PPC_INSNS_BASE = 0x0000000000000001ULL,
- /* integer operations instructions */
-#define PPC_INTEGER PPC_INSNS_BASE
- /* flow control instructions */
-#define PPC_FLOW PPC_INSNS_BASE
- /* virtual memory instructions */
-#define PPC_MEM PPC_INSNS_BASE
- /* ld/st with reservation instructions */
-#define PPC_RES PPC_INSNS_BASE
- /* spr/msr access instructions */
-#define PPC_MISC PPC_INSNS_BASE
- /* Deprecated instruction sets */
- /* Original POWER instruction set */
- PPC_POWER = 0x0000000000000002ULL,
- /* POWER2 instruction set extension */
- PPC_POWER2 = 0x0000000000000004ULL,
- /* Power RTC support */
- PPC_POWER_RTC = 0x0000000000000008ULL,
- /* Power-to-PowerPC bridge (601) */
- PPC_POWER_BR = 0x0000000000000010ULL,
- /* 64 bits PowerPC instruction set */
- PPC_64B = 0x0000000000000020ULL,
- /* New 64 bits extensions (PowerPC 2.0x) */
- PPC_64BX = 0x0000000000000040ULL,
- /* 64 bits hypervisor extensions */
- PPC_64H = 0x0000000000000080ULL,
- /* New wait instruction (PowerPC 2.0x) */
- PPC_WAIT = 0x0000000000000100ULL,
- /* Time base mftb instruction */
- PPC_MFTB = 0x0000000000000200ULL,
-
- /* Fixed-point unit extensions */
- /* PowerPC 602 specific */
- PPC_602_SPEC = 0x0000000000000400ULL,
- /* isel instruction */
- PPC_ISEL = 0x0000000000000800ULL,
- /* popcntb instruction */
- PPC_POPCNTB = 0x0000000000001000ULL,
- /* string load / store */
- PPC_STRING = 0x0000000000002000ULL,
-
- /* Floating-point unit extensions */
- /* Optional floating point instructions */
- PPC_FLOAT = 0x0000000000010000ULL,
- /* New floating-point extensions (PowerPC 2.0x) */
- PPC_FLOAT_EXT = 0x0000000000020000ULL,
- PPC_FLOAT_FSQRT = 0x0000000000040000ULL,
- PPC_FLOAT_FRES = 0x0000000000080000ULL,
- PPC_FLOAT_FRSQRTE = 0x0000000000100000ULL,
- PPC_FLOAT_FRSQRTES = 0x0000000000200000ULL,
- PPC_FLOAT_FSEL = 0x0000000000400000ULL,
- PPC_FLOAT_STFIWX = 0x0000000000800000ULL,
-
- /* Vector/SIMD extensions */
- /* Altivec support */
- PPC_ALTIVEC = 0x0000000001000000ULL,
- /* PowerPC 2.03 SPE extension */
- PPC_SPE = 0x0000000002000000ULL,
- /* PowerPC 2.03 SPE floating-point extension */
- PPC_SPEFPU = 0x0000000004000000ULL,
-
- /* Optional memory control instructions */
- PPC_MEM_TLBIA = 0x0000000010000000ULL,
- PPC_MEM_TLBIE = 0x0000000020000000ULL,
- PPC_MEM_TLBSYNC = 0x0000000040000000ULL,
- /* sync instruction */
- PPC_MEM_SYNC = 0x0000000080000000ULL,
- /* eieio instruction */
- PPC_MEM_EIEIO = 0x0000000100000000ULL,
-
- /* Cache control instructions */
- PPC_CACHE = 0x0000000200000000ULL,
- /* icbi instruction */
- PPC_CACHE_ICBI = 0x0000000400000000ULL,
- /* dcbz instruction with fixed cache line size */
- PPC_CACHE_DCBZ = 0x0000000800000000ULL,
- /* dcbz instruction with tunable cache line size */
- PPC_CACHE_DCBZT = 0x0000001000000000ULL,
- /* dcba instruction */
- PPC_CACHE_DCBA = 0x0000002000000000ULL,
- /* Freescale cache locking instructions */
- PPC_CACHE_LOCK = 0x0000004000000000ULL,
-
- /* MMU related extensions */
- /* external control instructions */
- PPC_EXTERN = 0x0000010000000000ULL,
- /* segment register access instructions */
- PPC_SEGMENT = 0x0000020000000000ULL,
- /* PowerPC 6xx TLB management instructions */
- PPC_6xx_TLB = 0x0000040000000000ULL,
- /* PowerPC 74xx TLB management instructions */
- PPC_74xx_TLB = 0x0000080000000000ULL,
- /* PowerPC 40x TLB management instructions */
- PPC_40x_TLB = 0x0000100000000000ULL,
- /* segment register access instructions for PowerPC 64 "bridge" */
- PPC_SEGMENT_64B = 0x0000200000000000ULL,
- /* SLB management */
- PPC_SLBI = 0x0000400000000000ULL,
-
- /* Embedded PowerPC dedicated instructions */
- PPC_WRTEE = 0x0001000000000000ULL,
- /* PowerPC 40x exception model */
- PPC_40x_EXCP = 0x0002000000000000ULL,
- /* PowerPC 405 Mac instructions */
- PPC_405_MAC = 0x0004000000000000ULL,
- /* PowerPC 440 specific instructions */
- PPC_440_SPEC = 0x0008000000000000ULL,
- /* BookE (embedded) PowerPC specification */
- PPC_BOOKE = 0x0010000000000000ULL,
- /* mfapidi instruction */
- PPC_MFAPIDI = 0x0020000000000000ULL,
- /* tlbiva instruction */
- PPC_TLBIVA = 0x0040000000000000ULL,
- /* tlbivax instruction */
- PPC_TLBIVAX = 0x0080000000000000ULL,
- /* PowerPC 4xx dedicated instructions */
- PPC_4xx_COMMON = 0x0100000000000000ULL,
- /* PowerPC 40x ibct instructions */
- PPC_40x_ICBT = 0x0200000000000000ULL,
- /* rfmci is not implemented in all BookE PowerPC */
- PPC_RFMCI = 0x0400000000000000ULL,
- /* rfdi instruction */
- PPC_RFDI = 0x0800000000000000ULL,
- /* DCR accesses */
- PPC_DCR = 0x1000000000000000ULL,
- /* DCR extended accesse */
- PPC_DCRX = 0x2000000000000000ULL,
- /* user-mode DCR access, implemented in PowerPC 460 */
- PPC_DCRUX = 0x4000000000000000ULL,
-};
-
-/*****************************************************************************/
/* PowerPC instructions table */
#if HOST_LONG_BITS == 64
#define OPC_ALIGN 8
#if defined(DO_PPC_STATISTICS)
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
+extern opcode_t opc_##name; \
OPCODES_SECTION opcode_t opc_##name = { \
.opc1 = op1, \
.opc2 = op2, \
}
#else
#define GEN_OPCODE(name, op1, op2, op3, invl, _typ) \
+extern opcode_t opc_##name; \
OPCODES_SECTION opcode_t opc_##name = { \
.opc1 = op1, \
.opc2 = op2, \
.oname = stringify(name), \
}
#define GEN_OPCODE2(name, onam, op1, op2, op3, invl, _typ) \
+extern opcode_t opc_##name; \
OPCODES_SECTION opcode_t opc_##name = { \
.opc1 = op1, \
.opc2 = op2, \
#endif
#define GEN_OPCODE_MARK(name) \
+extern opcode_t opc_##name; \
OPCODES_SECTION opcode_t opc_##name = { \
.opc1 = 0xFF, \
.opc2 = 0xFF, \
}
/* mtfsf */
-GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x02010000, PPC_FLOAT)
+GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00010000, PPC_FLOAT)
{
TCGv_i32 t0;
+ int L = ctx->opcode & 0x02000000;
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
/* NIP cannot be restored if the memory exception comes from an helper */
gen_update_nip(ctx, ctx->nip - 4);
gen_reset_fpstatus();
- t0 = tcg_const_i32(FM(ctx->opcode));
+ if (L)
+ t0 = tcg_const_i32(0xff);
+ else
+ t0 = tcg_const_i32(FM(ctx->opcode));
gen_helper_store_fpscr(cpu_fpr[rB(ctx->opcode)], t0);
tcg_temp_free_i32(t0);
if (unlikely(Rc(ctx->opcode) != 0)) {
{
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
if (unlikely(ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap16_i32(t0, t0);
- tcg_gen_extu_i32_tl(arg1, t0);
- tcg_temp_free_i32(t0);
-#else
- tcg_gen_bswap16_i32(arg1, arg1);
-#endif
+ tcg_gen_bswap16_tl(arg1, arg1);
}
}
static always_inline void gen_qemu_ld16s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
if (unlikely(ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0;
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap16_i32(t0, t0);
- tcg_gen_extu_i32_tl(arg1, t0);
+ tcg_gen_bswap16_tl(arg1, arg1);
tcg_gen_ext16s_tl(arg1, arg1);
- tcg_temp_free_i32(t0);
-#else
- tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
- tcg_gen_bswap16_i32(arg1, arg1);
- tcg_gen_ext16s_i32(arg1, arg1);
-#endif
} else {
tcg_gen_qemu_ld16s(arg1, arg2, ctx->mem_idx);
}
{
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
if (unlikely(ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap_i32(t0, t0);
- tcg_gen_extu_i32_tl(arg1, t0);
- tcg_temp_free_i32(t0);
-#else
- tcg_gen_bswap_i32(arg1, arg1);
-#endif
+ tcg_gen_bswap32_tl(arg1, arg1);
}
}
#if defined(TARGET_PPC64)
static always_inline void gen_qemu_ld32s(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
- if (unlikely(ctx->mem_idx)) {
- TCGv_i32 t0;
+ if (unlikely(ctx->le_mode)) {
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap_i32(t0, t0);
- tcg_gen_ext_i32_tl(arg1, t0);
- tcg_temp_free_i32(t0);
+ tcg_gen_bswap32_tl(arg1, arg1);
+ tcg_gen_ext32s_tl(arg1, arg1);
} else
tcg_gen_qemu_ld32s(arg1, arg2, ctx->mem_idx);
}
{
tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
if (unlikely(ctx->le_mode)) {
- tcg_gen_bswap_i64(arg1, arg1);
+ tcg_gen_bswap64_i64(arg1, arg1);
}
}
static always_inline void gen_qemu_st16(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
if (unlikely(ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0;
- TCGv t1;
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_ext16u_i32(t0, t0);
- tcg_gen_bswap16_i32(t0, t0);
- t1 = tcg_temp_new();
- tcg_gen_extu_i32_tl(t1, t0);
- tcg_temp_free_i32(t0);
- tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx);
- tcg_temp_free(t1);
-#else
TCGv t0 = tcg_temp_new();
tcg_gen_ext16u_tl(t0, arg1);
- tcg_gen_bswap16_i32(t0, t0);
+ tcg_gen_bswap16_tl(t0, t0);
tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
tcg_temp_free(t0);
-#endif
} else {
tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
}
static always_inline void gen_qemu_st32(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
if (unlikely(ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0;
- TCGv t1;
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap_i32(t0, t0);
- t1 = tcg_temp_new();
- tcg_gen_extu_i32_tl(t1, t0);
- tcg_temp_free_i32(t0);
- tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx);
- tcg_temp_free(t1);
-#else
- TCGv t0 = tcg_temp_new_i32();
- tcg_gen_bswap_i32(t0, arg1);
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_ext32u_tl(t0, arg1);
+ tcg_gen_bswap32_tl(t0, t0);
tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
tcg_temp_free(t0);
-#endif
} else {
tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
}
{
if (unlikely(ctx->le_mode)) {
TCGv_i64 t0 = tcg_temp_new_i64();
- tcg_gen_bswap_i64(t0, arg1);
+ tcg_gen_bswap64_i64(t0, arg1);
tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
tcg_temp_free_i64(t0);
} else
{
tcg_gen_qemu_ld16u(arg1, arg2, ctx->mem_idx);
if (likely(!ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap16_i32(t0, t0);
- tcg_gen_extu_i32_tl(arg1, t0);
- tcg_temp_free_i32(t0);
-#else
- tcg_gen_bswap16_i32(arg1, arg1);
-#endif
+ tcg_gen_bswap16_tl(arg1, arg1);
}
}
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER);
{
tcg_gen_qemu_ld32u(arg1, arg2, ctx->mem_idx);
if (likely(!ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap_i32(t0, t0);
- tcg_gen_extu_i32_tl(arg1, t0);
- tcg_temp_free_i32(t0);
-#else
- tcg_gen_bswap_i32(arg1, arg1);
-#endif
+ tcg_gen_bswap32_tl(arg1, arg1);
}
}
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
static void always_inline gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
if (likely(!ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0;
- TCGv t1;
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_ext16u_i32(t0, t0);
- tcg_gen_bswap16_i32(t0, t0);
- t1 = tcg_temp_new();
- tcg_gen_extu_i32_tl(t1, t0);
- tcg_temp_free_i32(t0);
- tcg_gen_qemu_st16(t1, arg2, ctx->mem_idx);
- tcg_temp_free(t1);
-#else
TCGv t0 = tcg_temp_new();
tcg_gen_ext16u_tl(t0, arg1);
- tcg_gen_bswap16_i32(t0, t0);
+ tcg_gen_bswap16_tl(t0, t0);
tcg_gen_qemu_st16(t0, arg2, ctx->mem_idx);
tcg_temp_free(t0);
-#endif
} else {
tcg_gen_qemu_st16(arg1, arg2, ctx->mem_idx);
}
static void always_inline gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
if (likely(!ctx->le_mode)) {
-#if defined(TARGET_PPC64)
- TCGv_i32 t0;
- TCGv t1;
- t0 = tcg_temp_new_i32();
- tcg_gen_trunc_tl_i32(t0, arg1);
- tcg_gen_bswap_i32(t0, t0);
- t1 = tcg_temp_new();
- tcg_gen_extu_i32_tl(t1, t0);
- tcg_temp_free_i32(t0);
- tcg_gen_qemu_st32(t1, arg2, ctx->mem_idx);
- tcg_temp_free(t1);
-#else
- TCGv t0 = tcg_temp_new_i32();
- tcg_gen_bswap_i32(t0, arg1);
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_ext32u_tl(t0, arg1);
+ tcg_gen_bswap32_tl(t0, t0);
tcg_gen_qemu_st32(t0, arg2, ctx->mem_idx);
tcg_temp_free(t0);
-#endif
} else {
tcg_gen_qemu_st32(arg1, arg2, ctx->mem_idx);
}
tcg_gen_andi_tl(cpu_xer, cpu_xer, ~(1 << XER_SO | 1 << XER_OV | 1 << XER_CA));
}
-/* mfcr */
+/* mfcr mfocrf */
GEN_HANDLER(mfcr, 0x1F, 0x13, 0x00, 0x00000801, PPC_MISC)
{
uint32_t crm, crn;
if (likely(ctx->opcode & 0x00100000)) {
crm = CRM(ctx->opcode);
- if (likely((crm ^ (crm - 1)) == 0)) {
- crn = ffs(crm);
+ if (likely(crm && ((crm & (crm - 1)) == 0))) {
+ crn = ctz32 (crm);
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], cpu_crf[7 - crn]);
+ tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)],
+ cpu_gpr[rD(ctx->opcode)], crn * 4);
}
} else {
- gen_helper_load_cr(cpu_gpr[rD(ctx->opcode)]);
+ TCGv_i32 t0 = tcg_temp_new_i32();
+ tcg_gen_mov_i32(t0, cpu_crf[0]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[1]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[2]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[3]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[4]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[5]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[6]);
+ tcg_gen_shli_i32(t0, t0, 4);
+ tcg_gen_or_i32(t0, t0, cpu_crf[7]);
+ tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0);
+ tcg_temp_free_i32(t0);
}
}
* allowing userland application to read the PVR
*/
if (sprn != SPR_PVR) {
- if (loglevel != 0) {
- fprintf(logfile, "Trying to read privileged spr %d %03x at "
+ qemu_log("Trying to read privileged spr %d %03x at "
ADDRX "\n", sprn, sprn, ctx->nip);
- }
printf("Trying to read privileged spr %d %03x at " ADDRX "\n",
sprn, sprn, ctx->nip);
}
}
} else {
/* Not defined */
- if (loglevel != 0) {
- fprintf(logfile, "Trying to read invalid spr %d %03x at "
+ qemu_log("Trying to read invalid spr %d %03x at "
ADDRX "\n", sprn, sprn, ctx->nip);
- }
printf("Trying to read invalid spr %d %03x at " ADDRX "\n",
sprn, sprn, ctx->nip);
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
gen_op_mfspr(ctx);
}
-/* mtcrf */
+/* mtcrf mtocrf*/
GEN_HANDLER(mtcrf, 0x1F, 0x10, 0x04, 0x00000801, PPC_MISC)
{
uint32_t crm, crn;
crm = CRM(ctx->opcode);
- if (likely((ctx->opcode & 0x00100000) || (crm ^ (crm - 1)) == 0)) {
+ if (likely((ctx->opcode & 0x00100000))) {
+ if (crm && ((crm & (crm - 1)) == 0)) {
+ TCGv_i32 temp = tcg_temp_new_i32();
+ crn = ctz32 (crm);
+ tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
+ tcg_gen_shri_i32(temp, temp, crn * 4);
+ tcg_gen_andi_i32(cpu_crf[7 - crn], temp, 0xf);
+ tcg_temp_free_i32(temp);
+ }
+ } else {
TCGv_i32 temp = tcg_temp_new_i32();
- crn = ffs(crm);
tcg_gen_trunc_tl_i32(temp, cpu_gpr[rS(ctx->opcode)]);
- tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
- tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
- tcg_temp_free_i32(temp);
- } else {
- TCGv_i32 temp = tcg_const_i32(crm);
- gen_helper_store_cr(cpu_gpr[rS(ctx->opcode)], temp);
+ for (crn = 0 ; crn < 8 ; crn++) {
+ if (crm & (1 << crn)) {
+ tcg_gen_shri_i32(cpu_crf[7 - crn], temp, crn * 4);
+ tcg_gen_andi_i32(cpu_crf[7 - crn], cpu_crf[7 - crn], 0xf);
+ }
+ }
tcg_temp_free_i32(temp);
}
}
(*write_cb)(ctx, sprn, rS(ctx->opcode));
} else {
/* Privilege exception */
- if (loglevel != 0) {
- fprintf(logfile, "Trying to write privileged spr %d %03x at "
+ qemu_log("Trying to write privileged spr %d %03x at "
ADDRX "\n", sprn, sprn, ctx->nip);
- }
printf("Trying to write privileged spr %d %03x at " ADDRX "\n",
sprn, sprn, ctx->nip);
gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
}
} else {
/* Not defined */
- if (loglevel != 0) {
- fprintf(logfile, "Trying to write invalid spr %d %03x at "
+ qemu_log("Trying to write invalid spr %d %03x at "
ADDRX "\n", sprn, sprn, ctx->nip);
- }
printf("Trying to write invalid spr %d %03x at " ADDRX "\n",
sprn, sprn, ctx->nip);
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_SPR);
tcg_temp_free(t0);
}
+/* dst / dstt */
+GEN_HANDLER(dst, 0x1F, 0x16, 0x0A, 0x01800001, PPC_ALTIVEC)
+{
+ if (rA(ctx->opcode) == 0) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ } else {
+ /* interpreted as no-op */
+ }
+}
+
+/* dstst /dststt */
+GEN_HANDLER(dstst, 0x1F, 0x16, 0x0B, 0x02000001, PPC_ALTIVEC)
+{
+ if (rA(ctx->opcode) == 0) {
+ gen_inval_exception(ctx, POWERPC_EXCP_INVAL_LSWX);
+ } else {
+ /* interpreted as no-op */
+ }
+
+}
+
+/* dss / dssall */
+GEN_HANDLER(dss, 0x1F, 0x16, 0x19, 0x019FF801, PPC_ALTIVEC)
+{
+ /* interpreted as no-op */
+}
+
/* icbi */
GEN_HANDLER(icbi, 0x1F, 0x16, 0x1E, 0x03E00001, PPC_CACHE_ICBI)
{
return;
}
t0 = tcg_const_tl(SR(ctx->opcode));
- gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+ gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
tcg_temp_free(t0);
#endif
}
t0 = tcg_temp_new();
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
tcg_gen_andi_tl(t0, t0, 0xF);
- gen_helper_load_slb(cpu_gpr[rD(ctx->opcode)], t0);
+ gen_helper_load_sr(cpu_gpr[rD(ctx->opcode)], t0);
tcg_temp_free(t0);
#endif
}
return;
}
t0 = tcg_const_tl(SR(ctx->opcode));
- gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+ gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
tcg_temp_free(t0);
#endif
}
t0 = tcg_temp_new();
tcg_gen_shri_tl(t0, cpu_gpr[rB(ctx->opcode)], 28);
tcg_gen_andi_tl(t0, t0, 0xF);
- gen_helper_store_slb(t0, cpu_gpr[rS(ctx->opcode)]);
+ gen_helper_store_sr(t0, cpu_gpr[rS(ctx->opcode)]);
tcg_temp_free(t0);
#endif
}
+
+/* slbmte */
+GEN_HANDLER2(slbmte, "slbmte", 0x1F, 0x12, 0x0C, 0x00000000, PPC_SEGMENT_64B)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+ return;
+ }
+ gen_helper_store_slb(cpu_gpr[rB(ctx->opcode)], cpu_gpr[rS(ctx->opcode)]);
+#endif
+}
+
#endif /* defined(TARGET_PPC64) */
/*** Lookaside buffer management ***/
#endif
}
+/* tlbiel */
+GEN_HANDLER(tlbiel, 0x1F, 0x12, 0x08, 0x03FF0001, PPC_MEM_TLBIE)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+ if (unlikely(!ctx->mem_idx)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return;
+ }
+ gen_helper_tlbie(cpu_gpr[rB(ctx->opcode)]);
+#endif
+}
+
/* tlbie */
GEN_HANDLER(tlbie, 0x1F, 0x12, 0x09, 0x03FF0001, PPC_MEM_TLBIE)
{
/* Stop translation to have a chance to raise an exception */
gen_stop_exception(ctx);
} else {
- tcg_gen_andi_tl(cpu_msr, cpu_msr, (1 << MSR_EE));
+ tcg_gen_andi_tl(cpu_msr, cpu_msr, ~(1 << MSR_EE));
}
#endif
}
tcg_temp_free(EA); \
}
+#define GEN_VR_LVE(name, opc2, opc3) \
+ GEN_HANDLER(lve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
+ { \
+ TCGv EA; \
+ TCGv_ptr rs; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ gen_set_access_type(ctx, ACCESS_INT); \
+ EA = tcg_temp_new(); \
+ gen_addr_reg_index(ctx, EA); \
+ rs = gen_avr_ptr(rS(ctx->opcode)); \
+ gen_helper_lve##name (rs, EA); \
+ tcg_temp_free(EA); \
+ tcg_temp_free_ptr(rs); \
+ }
+
+#define GEN_VR_STVE(name, opc2, opc3) \
+ GEN_HANDLER(stve##name, 0x1F, opc2, opc3, 0x00000001, PPC_ALTIVEC) \
+ { \
+ TCGv EA; \
+ TCGv_ptr rs; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ gen_set_access_type(ctx, ACCESS_INT); \
+ EA = tcg_temp_new(); \
+ gen_addr_reg_index(ctx, EA); \
+ rs = gen_avr_ptr(rS(ctx->opcode)); \
+ gen_helper_stve##name (rs, EA); \
+ tcg_temp_free(EA); \
+ tcg_temp_free_ptr(rs); \
+ }
+
GEN_VR_LDX(lvx, 0x07, 0x03);
/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
GEN_VR_LDX(lvxl, 0x07, 0x0B);
+GEN_VR_LVE(bx, 0x07, 0x00);
+GEN_VR_LVE(hx, 0x07, 0x01);
+GEN_VR_LVE(wx, 0x07, 0x02);
+
GEN_VR_STX(svx, 0x07, 0x07);
/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
GEN_VR_STX(svxl, 0x07, 0x0F);
+GEN_VR_STVE(bx, 0x07, 0x04);
+GEN_VR_STVE(hx, 0x07, 0x05);
+GEN_VR_STVE(wx, 0x07, 0x06);
+
+GEN_HANDLER(lvsl, 0x1f, 0x06, 0x00, 0x00000001, PPC_ALTIVEC)
+{
+ TCGv_ptr rd;
+ TCGv EA;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ rd = gen_avr_ptr(rD(ctx->opcode));
+ gen_helper_lvsl(rd, EA);
+ tcg_temp_free(EA);
+ tcg_temp_free_ptr(rd);
+}
+
+GEN_HANDLER(lvsr, 0x1f, 0x06, 0x01, 0x00000001, PPC_ALTIVEC)
+{
+ TCGv_ptr rd;
+ TCGv EA;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ EA = tcg_temp_new();
+ gen_addr_reg_index(ctx, EA);
+ rd = gen_avr_ptr(rD(ctx->opcode));
+ gen_helper_lvsr(rd, EA);
+ tcg_temp_free(EA);
+ tcg_temp_free_ptr(rd);
+}
+
+GEN_HANDLER(mfvscr, 0x04, 0x2, 0x18, 0x001ff800, PPC_ALTIVEC)
+{
+ TCGv_i32 t;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ tcg_gen_movi_i64(cpu_avrh[rD(ctx->opcode)], 0);
+ t = tcg_temp_new_i32();
+ tcg_gen_ld_i32(t, cpu_env, offsetof(CPUState, vscr));
+ tcg_gen_extu_i32_i64(cpu_avrl[rD(ctx->opcode)], t);
+ tcg_temp_free_i32(t);
+}
+
+GEN_HANDLER(mtvscr, 0x04, 0x2, 0x19, 0x03ff0000, PPC_ALTIVEC)
+{
+ TCGv_ptr p;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ p = gen_avr_ptr(rD(ctx->opcode));
+ gen_helper_mtvscr(p);
+ tcg_temp_free_ptr(p);
+}
+
/* Logical operations */
#define GEN_VX_LOGICAL(name, tcg_op, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
GEN_VXFORM(vsraw, 2, 14);
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
+GEN_VXFORM(vaddcuw, 0, 6);
+GEN_VXFORM(vsubcuw, 0, 22);
+GEN_VXFORM(vaddubs, 0, 8);
+GEN_VXFORM(vadduhs, 0, 9);
+GEN_VXFORM(vadduws, 0, 10);
+GEN_VXFORM(vaddsbs, 0, 12);
+GEN_VXFORM(vaddshs, 0, 13);
+GEN_VXFORM(vaddsws, 0, 14);
+GEN_VXFORM(vsububs, 0, 24);
+GEN_VXFORM(vsubuhs, 0, 25);
+GEN_VXFORM(vsubuws, 0, 26);
+GEN_VXFORM(vsubsbs, 0, 28);
+GEN_VXFORM(vsubshs, 0, 29);
+GEN_VXFORM(vsubsws, 0, 30);
+GEN_VXFORM(vrlb, 2, 0);
+GEN_VXFORM(vrlh, 2, 1);
+GEN_VXFORM(vrlw, 2, 2);
+GEN_VXFORM(vsl, 2, 7);
+GEN_VXFORM(vsr, 2, 11);
+GEN_VXFORM(vpkuhum, 7, 0);
+GEN_VXFORM(vpkuwum, 7, 1);
+GEN_VXFORM(vpkuhus, 7, 2);
+GEN_VXFORM(vpkuwus, 7, 3);
+GEN_VXFORM(vpkshus, 7, 4);
+GEN_VXFORM(vpkswus, 7, 5);
+GEN_VXFORM(vpkshss, 7, 6);
+GEN_VXFORM(vpkswss, 7, 7);
+GEN_VXFORM(vpkpx, 7, 12);
+GEN_VXFORM(vsum4ubs, 4, 24);
+GEN_VXFORM(vsum4sbs, 4, 28);
+GEN_VXFORM(vsum4shs, 4, 25);
+GEN_VXFORM(vsum2sws, 4, 26);
+GEN_VXFORM(vsumsws, 4, 30);
+GEN_VXFORM(vaddfp, 5, 0);
+GEN_VXFORM(vsubfp, 5, 1);
+GEN_VXFORM(vmaxfp, 5, 16);
+GEN_VXFORM(vminfp, 5, 17);
+
+#define GEN_VXRFORM1(opname, name, str, opc2, opc3) \
+ GEN_HANDLER2(name, str, 0x4, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr ra, rb, rd; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ ra = gen_avr_ptr(rA(ctx->opcode)); \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##opname (rd, ra, rb); \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+#define GEN_VXRFORM(name, opc2, opc3) \
+ GEN_VXRFORM1(name, name, #name, opc2, opc3) \
+ GEN_VXRFORM1(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
+
+GEN_VXRFORM(vcmpequb, 3, 0)
+GEN_VXRFORM(vcmpequh, 3, 1)
+GEN_VXRFORM(vcmpequw, 3, 2)
+GEN_VXRFORM(vcmpgtsb, 3, 12)
+GEN_VXRFORM(vcmpgtsh, 3, 13)
+GEN_VXRFORM(vcmpgtsw, 3, 14)
+GEN_VXRFORM(vcmpgtub, 3, 8)
+GEN_VXRFORM(vcmpgtuh, 3, 9)
+GEN_VXRFORM(vcmpgtuw, 3, 10)
+GEN_VXRFORM(vcmpeqfp, 3, 3)
+GEN_VXRFORM(vcmpgefp, 3, 7)
+GEN_VXRFORM(vcmpgtfp, 3, 11)
+GEN_VXRFORM(vcmpbfp, 3, 15)
+
+#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+ GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr rd; \
+ TCGv_i32 simm; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ simm = tcg_const_i32(SIMM5(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name (rd, simm); \
+ tcg_temp_free_i32(simm); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+GEN_VXFORM_SIMM(vspltisb, 6, 12);
+GEN_VXFORM_SIMM(vspltish, 6, 13);
+GEN_VXFORM_SIMM(vspltisw, 6, 14);
+
+#define GEN_VXFORM_NOA(name, opc2, opc3) \
+ GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr rb, rd; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name (rd, rb); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+GEN_VXFORM_NOA(vupkhsb, 7, 8);
+GEN_VXFORM_NOA(vupkhsh, 7, 9);
+GEN_VXFORM_NOA(vupklsb, 7, 10);
+GEN_VXFORM_NOA(vupklsh, 7, 11);
+GEN_VXFORM_NOA(vupkhpx, 7, 13);
+GEN_VXFORM_NOA(vupklpx, 7, 15);
+GEN_VXFORM_NOA(vrefp, 5, 4);
+GEN_VXFORM_NOA(vrsqrtefp, 5, 5);
+GEN_VXFORM_NOA(vlogefp, 5, 7);
+GEN_VXFORM_NOA(vrfim, 5, 8);
+GEN_VXFORM_NOA(vrfin, 5, 9);
+GEN_VXFORM_NOA(vrfip, 5, 10);
+GEN_VXFORM_NOA(vrfiz, 5, 11);
+
+#define GEN_VXFORM_SIMM(name, opc2, opc3) \
+ GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr rd; \
+ TCGv_i32 simm; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ simm = tcg_const_i32(SIMM5(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name (rd, simm); \
+ tcg_temp_free_i32(simm); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+#define GEN_VXFORM_UIMM(name, opc2, opc3) \
+ GEN_HANDLER(name, 0x04, opc2, opc3, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr rb, rd; \
+ TCGv_i32 uimm; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ gen_helper_##name (rd, rb, uimm); \
+ tcg_temp_free_i32(uimm); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+GEN_VXFORM_UIMM(vspltb, 6, 8);
+GEN_VXFORM_UIMM(vsplth, 6, 9);
+GEN_VXFORM_UIMM(vspltw, 6, 10);
+GEN_VXFORM_UIMM(vcfux, 5, 12);
+GEN_VXFORM_UIMM(vcfsx, 5, 13);
+GEN_VXFORM_UIMM(vctuxs, 5, 14);
+GEN_VXFORM_UIMM(vctsxs, 5, 15);
+
+GEN_HANDLER(vsldoi, 0x04, 0x16, 0xFF, 0x00000400, PPC_ALTIVEC)
+{
+ TCGv_ptr ra, rb, rd;
+ TCGv_i32 sh;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ ra = gen_avr_ptr(rA(ctx->opcode));
+ rb = gen_avr_ptr(rB(ctx->opcode));
+ rd = gen_avr_ptr(rD(ctx->opcode));
+ sh = tcg_const_i32(VSH(ctx->opcode));
+ gen_helper_vsldoi (rd, ra, rb, sh);
+ tcg_temp_free_ptr(ra);
+ tcg_temp_free_ptr(rb);
+ tcg_temp_free_ptr(rd);
+ tcg_temp_free_i32(sh);
+}
+
+#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
+ GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC) \
+ { \
+ TCGv_ptr ra, rb, rc, rd; \
+ if (unlikely(!ctx->altivec_enabled)) { \
+ gen_exception(ctx, POWERPC_EXCP_VPU); \
+ return; \
+ } \
+ ra = gen_avr_ptr(rA(ctx->opcode)); \
+ rb = gen_avr_ptr(rB(ctx->opcode)); \
+ rc = gen_avr_ptr(rC(ctx->opcode)); \
+ rd = gen_avr_ptr(rD(ctx->opcode)); \
+ if (Rc(ctx->opcode)) { \
+ gen_helper_##name1 (rd, ra, rb, rc); \
+ } else { \
+ gen_helper_##name0 (rd, ra, rb, rc); \
+ } \
+ tcg_temp_free_ptr(ra); \
+ tcg_temp_free_ptr(rb); \
+ tcg_temp_free_ptr(rc); \
+ tcg_temp_free_ptr(rd); \
+ }
+
+GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16)
+
+GEN_HANDLER(vmladduhm, 0x04, 0x11, 0xFF, 0x00000000, PPC_ALTIVEC)
+{
+ TCGv_ptr ra, rb, rc, rd;
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+ ra = gen_avr_ptr(rA(ctx->opcode));
+ rb = gen_avr_ptr(rB(ctx->opcode));
+ rc = gen_avr_ptr(rC(ctx->opcode));
+ rd = gen_avr_ptr(rD(ctx->opcode));
+ gen_helper_vmladduhm(rd, ra, rb, rc);
+ tcg_temp_free_ptr(ra);
+ tcg_temp_free_ptr(rb);
+ tcg_temp_free_ptr(rc);
+ tcg_temp_free_ptr(rd);
+}
+
+GEN_VAFORM_PAIRED(vmsumubm, vmsummbm, 18)
+GEN_VAFORM_PAIRED(vmsumuhm, vmsumuhs, 19)
+GEN_VAFORM_PAIRED(vmsumshm, vmsumshs, 20)
+GEN_VAFORM_PAIRED(vsel, vperm, 21)
+GEN_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
/*** SPE extension ***/
/* Register moves */
GEN_SPEFPUOP_COMP_64(evfststeq);
/* Opcodes definitions */
-GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(evfsadd, evfssub, 0x00, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsabs, evfsnabs, 0x02, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(evfsneg, speundef, 0x03, 0x0A, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(evfsmul, evfsdiv, 0x04, 0x0A, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscmpgt, evfscmplt, 0x06, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscmpeq, speundef, 0x07, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscfui, evfscfsi, 0x08, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfscfuf, evfscfsf, 0x09, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctui, evfsctsi, 0x0A, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctuf, evfsctsf, 0x0B, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctuiz, speundef, 0x0C, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfsctsiz, speundef, 0x0D, 0x0A, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(evfststgt, evfststlt, 0x0E, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(evfststeq, speundef, 0x0F, 0x0A, 0x00600000, PPC_SPE_SINGLE); //
/* Single precision floating-point operations */
/* Arithmetic */
GEN_SPEFPUOP_COMP_32(efststeq);
/* Opcodes definitions */
-GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efsadd, efssub, 0x00, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(efsabs, efsnabs, 0x02, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(efsneg, speundef, 0x03, 0x0B, 0x0000F800, PPC_SPE_SINGLE); //
+GEN_SPE(efsmul, efsdiv, 0x04, 0x0B, 0x00000000, PPC_SPE_SINGLE); //
+GEN_SPE(efscmpgt, efscmplt, 0x06, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efscmpeq, efscfd, 0x07, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efscfui, efscfsi, 0x08, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efscfuf, efscfsf, 0x09, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctui, efsctsi, 0x0A, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctuf, efsctsf, 0x0B, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctuiz, speundef, 0x0C, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efsctsiz, speundef, 0x0D, 0x0B, 0x00180000, PPC_SPE_SINGLE); //
+GEN_SPE(efststgt, efststlt, 0x0E, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
+GEN_SPE(efststeq, speundef, 0x0F, 0x0B, 0x00600000, PPC_SPE_SINGLE); //
/* Double precision floating-point operations */
/* Arithmetic */
GEN_SPEFPUOP_COMP_64(efdtsteq);
/* Opcodes definitions */
-GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPEFPU); //
-GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPEFPU); //
-GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPEFPU); //
-GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPEFPU); //
-GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPEFPU); //
+GEN_SPE(efdadd, efdsub, 0x10, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfuid, efdcfsid, 0x11, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdabs, efdnabs, 0x12, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
+GEN_SPE(efdneg, speundef, 0x13, 0x0B, 0x0000F800, PPC_SPE_DOUBLE); //
+GEN_SPE(efdmul, efddiv, 0x14, 0x0B, 0x00000000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuidz, efdctsidz, 0x15, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcmpgt, efdcmplt, 0x16, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcmpeq, efdcfs, 0x17, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfui, efdcfsi, 0x18, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdcfuf, efdcfsf, 0x19, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctui, efdctsi, 0x1A, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuf, efdctsf, 0x1B, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctuiz, speundef, 0x1C, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdctsiz, speundef, 0x1D, 0x0B, 0x00180000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdtstgt, efdtstlt, 0x1E, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
+GEN_SPE(efdtsteq, speundef, 0x1F, 0x0B, 0x00600000, PPC_SPE_DOUBLE); //
/* End opcode list */
GEN_OPCODE_MARK(end);
lj++;
while (lj < j)
gen_opc_instr_start[lj++] = 0;
- gen_opc_pc[lj] = ctx.nip;
- gen_opc_instr_start[lj] = 1;
- gen_opc_icount[lj] = num_insns;
}
+ gen_opc_pc[lj] = ctx.nip;
+ gen_opc_instr_start[lj] = 1;
+ gen_opc_icount[lj] = num_insns;
}
-#if defined PPC_DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "----------------\n");
- fprintf(logfile, "nip=" ADDRX " super=%d ir=%d\n",
- ctx.nip, ctx.mem_idx, (int)msr_ir);
- }
-#endif
+ LOG_DISAS("----------------\n");
+ LOG_DISAS("nip=" ADDRX " super=%d ir=%d\n",
+ ctx.nip, ctx.mem_idx, (int)msr_ir);
if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
gen_io_start();
if (unlikely(ctx.le_mode)) {
} else {
ctx.opcode = ldl_code(ctx.nip);
}
-#if defined PPC_DEBUG_DISAS
- if (loglevel & CPU_LOG_TB_IN_ASM) {
- fprintf(logfile, "translate opcode %08x (%02x %02x %02x) (%s)\n",
+ LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
opc3(ctx.opcode), little_endian ? "little" : "big");
- }
-#endif
ctx.nip += 4;
table = env->opcodes;
num_insns++;
}
/* Is opcode *REALLY* valid ? */
if (unlikely(handler->handler == &gen_invalid)) {
- if (loglevel != 0) {
- fprintf(logfile, "invalid/unsupported opcode: "
- "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
- opc1(ctx.opcode), opc2(ctx.opcode),
- opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
+ if (qemu_log_enabled()) {
+ qemu_log("invalid/unsupported opcode: "
+ "%02x - %02x - %02x (%08x) " ADDRX " %d\n",
+ opc1(ctx.opcode), opc2(ctx.opcode),
+ opc3(ctx.opcode), ctx.opcode, ctx.nip - 4, (int)msr_ir);
} else {
printf("invalid/unsupported opcode: "
"%02x - %02x - %02x (%08x) " ADDRX " %d\n",
}
} else {
if (unlikely((ctx.opcode & handler->inval) != 0)) {
- if (loglevel != 0) {
- fprintf(logfile, "invalid bits: %08x for opcode: "
- "%02x - %02x - %02x (%08x) " ADDRX "\n",
- ctx.opcode & handler->inval, opc1(ctx.opcode),
- opc2(ctx.opcode), opc3(ctx.opcode),
- ctx.opcode, ctx.nip - 4);
+ if (qemu_log_enabled()) {
+ qemu_log("invalid bits: %08x for opcode: "
+ "%02x - %02x - %02x (%08x) " ADDRX "\n",
+ ctx.opcode & handler->inval, opc1(ctx.opcode),
+ opc2(ctx.opcode), opc3(ctx.opcode),
+ ctx.opcode, ctx.nip - 4);
} else {
printf("invalid bits: %08x for opcode: "
"%02x - %02x - %02x (%08x) " ADDRX "\n",
gen_exception(ctxp, POWERPC_EXCP_TRACE);
} else if (unlikely(((ctx.nip & (TARGET_PAGE_SIZE - 1)) == 0) ||
(env->singlestep_enabled) ||
+ singlestep ||
num_insns >= max_insns)) {
/* if we reach a page boundary or are single stepping, stop
* generation
*/
break;
}
-#if defined (DO_SINGLE_STEP)
- break;
-#endif
}
if (tb->cflags & CF_LAST_IO)
gen_io_end();
tb->icount = num_insns;
}
#if defined(DEBUG_DISAS)
- if (loglevel & CPU_LOG_TB_CPU) {
- fprintf(logfile, "---------------- excp: %04x\n", ctx.exception);
- cpu_dump_state(env, logfile, fprintf, 0);
- }
- if (loglevel & CPU_LOG_TB_IN_ASM) {
+ qemu_log_mask(CPU_LOG_TB_CPU, "---------------- excp: %04x\n", ctx.exception);
+ log_cpu_state_mask(CPU_LOG_TB_CPU, env, 0);
+ if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
int flags;
flags = env->bfd_mach;
flags |= ctx.le_mode << 16;
- fprintf(logfile, "IN: %s\n", lookup_symbol(pc_start));
- target_disas(logfile, pc_start, ctx.nip - pc_start, flags);
- fprintf(logfile, "\n");
+ qemu_log("IN: %s\n", lookup_symbol(pc_start));
+ log_target_disas(pc_start, ctx.nip - pc_start, flags);
+ qemu_log("\n");
}
#endif
}