aboutsummaryrefslogtreecommitdiff
path: root/target/ppc/translate
diff options
context:
space:
mode:
Diffstat (limited to 'target/ppc/translate')
-rw-r--r--target/ppc/translate/branch-impl.c.inc33
-rw-r--r--target/ppc/translate/dfp-impl.c.inc401
-rw-r--r--target/ppc/translate/dfp-ops.c.inc165
-rw-r--r--target/ppc/translate/fixedpoint-impl.c.inc354
-rw-r--r--target/ppc/translate/fp-impl.c.inc842
-rw-r--r--target/ppc/translate/fp-ops.c.inc41
-rw-r--r--target/ppc/translate/processor-ctrl-impl.c.inc105
-rw-r--r--target/ppc/translate/spe-impl.c.inc97
-rw-r--r--target/ppc/translate/storage-ctrl-impl.c.inc248
-rw-r--r--target/ppc/translate/vector-impl.c.inc56
-rw-r--r--target/ppc/translate/vmx-impl.c.inc2504
-rw-r--r--target/ppc/translate/vmx-ops.c.inc97
-rw-r--r--target/ppc/translate/vsx-impl.c.inc2342
-rw-r--r--target/ppc/translate/vsx-ops.c.inc101
14 files changed, 4894 insertions, 2492 deletions
diff --git a/target/ppc/translate/branch-impl.c.inc b/target/ppc/translate/branch-impl.c.inc
new file mode 100644
index 0000000000..fb0fcf30cc
--- /dev/null
+++ b/target/ppc/translate/branch-impl.c.inc
@@ -0,0 +1,33 @@
+/*
+ * Power ISA decode for branch instructions
+ *
+ * Copyright IBM Corp. 2021
+ *
+ * Authors:
+ * Daniel Henrique Barboza <danielhb413@gmail.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+
+static bool trans_RFEBB(DisasContext *ctx, arg_XL_s *arg)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA207S);
+
+ translator_io_start(&ctx->base);
+ gen_update_cfar(ctx, ctx->cia);
+ gen_helper_rfebb(tcg_env, cpu_gpr[arg->s]);
+
+ ctx->base.is_jmp = DISAS_CHAIN;
+
+ return true;
+}
+#else
+static bool trans_RFEBB(DisasContext *ctx, arg_XL_s *arg)
+{
+ gen_invalid(ctx);
+ return true;
+}
+#endif
diff --git a/target/ppc/translate/dfp-impl.c.inc b/target/ppc/translate/dfp-impl.c.inc
index 6c556dc2e1..371076582b 100644
--- a/target/ppc/translate/dfp-impl.c.inc
+++ b/target/ppc/translate/dfp-impl.c.inc
@@ -3,230 +3,207 @@
static inline TCGv_ptr gen_fprp_ptr(int reg)
{
TCGv_ptr r = tcg_temp_new_ptr();
- tcg_gen_addi_ptr(r, cpu_env, offsetof(CPUPPCState, vsr[reg].u64[0]));
+ tcg_gen_addi_ptr(r, tcg_env, offsetof(CPUPPCState, vsr[reg].u64[0]));
return r;
}
-#define GEN_DFP_T_A_B_Rc(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr rd, ra, rb; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- rd = gen_fprp_ptr(rD(ctx->opcode)); \
- ra = gen_fprp_ptr(rA(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- gen_helper_##name(cpu_env, rd, ra, rb); \
- if (unlikely(Rc(ctx->opcode) != 0)) { \
- gen_set_cr1_from_fpscr(ctx); \
- } \
- tcg_temp_free_ptr(rd); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
+#define TRANS_DFP_T_A_B_Rc(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rt, ra, rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rt = gen_fprp_ptr(a->rt); \
+ ra = gen_fprp_ptr(a->ra); \
+ rb = gen_fprp_ptr(a->rb); \
+ gen_helper_##NAME(tcg_env, rt, ra, rb); \
+ if (unlikely(a->rc)) { \
+ gen_set_cr1_from_fpscr(ctx); \
+ } \
+ return true; \
}
-#define GEN_DFP_BF_A_B(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr ra, rb; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- ra = gen_fprp_ptr(rA(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
- cpu_env, ra, rb); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
+#define TRANS_DFP_BF_A_B(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr ra, rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ ra = gen_fprp_ptr(a->ra); \
+ rb = gen_fprp_ptr(a->rb); \
+ gen_helper_##NAME(cpu_crf[a->bf], \
+ tcg_env, ra, rb); \
+ return true; \
}
-#define GEN_DFP_BF_I_B(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_i32 uim; \
- TCGv_ptr rb; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- uim = tcg_const_i32(UIMM5(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
- cpu_env, uim, rb); \
- tcg_temp_free_i32(uim); \
- tcg_temp_free_ptr(rb); \
+#define TRANS_DFP_BF_I_B(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rb = gen_fprp_ptr(a->rb); \
+ gen_helper_##NAME(cpu_crf[a->bf], \
+ tcg_env, tcg_constant_i32(a->uim), rb);\
+ return true; \
}
-#define GEN_DFP_BF_A_DCM(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr ra; \
- TCGv_i32 dcm; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- ra = gen_fprp_ptr(rA(ctx->opcode)); \
- dcm = tcg_const_i32(DCM(ctx->opcode)); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], \
- cpu_env, ra, dcm); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_i32(dcm); \
+#define TRANS_DFP_BF_A_DCM(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr ra; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ ra = gen_fprp_ptr(a->fra); \
+ gen_helper_##NAME(cpu_crf[a->bf], \
+ tcg_env, ra, tcg_constant_i32(a->dm)); \
+ return true; \
}
-#define GEN_DFP_T_B_U32_U32_Rc(name, u32f1, u32f2) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr rt, rb; \
- TCGv_i32 u32_1, u32_2; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- rt = gen_fprp_ptr(rD(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- u32_1 = tcg_const_i32(u32f1(ctx->opcode)); \
- u32_2 = tcg_const_i32(u32f2(ctx->opcode)); \
- gen_helper_##name(cpu_env, rt, rb, u32_1, u32_2); \
- if (unlikely(Rc(ctx->opcode) != 0)) { \
- gen_set_cr1_from_fpscr(ctx); \
- } \
- tcg_temp_free_ptr(rt); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_i32(u32_1); \
- tcg_temp_free_i32(u32_2); \
+#define TRANS_DFP_T_B_U32_U32_Rc(NAME, U32F1, U32F2) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rt, rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rt = gen_fprp_ptr(a->frt); \
+ rb = gen_fprp_ptr(a->frb); \
+ gen_helper_##NAME(tcg_env, rt, rb, \
+ tcg_constant_i32(a->U32F1), \
+ tcg_constant_i32(a->U32F2)); \
+ if (unlikely(a->rc)) { \
+ gen_set_cr1_from_fpscr(ctx); \
+ } \
+ return true; \
}
-#define GEN_DFP_T_A_B_I32_Rc(name, i32fld) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr rt, ra, rb; \
- TCGv_i32 i32; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- rt = gen_fprp_ptr(rD(ctx->opcode)); \
- ra = gen_fprp_ptr(rA(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- i32 = tcg_const_i32(i32fld(ctx->opcode)); \
- gen_helper_##name(cpu_env, rt, ra, rb, i32); \
- if (unlikely(Rc(ctx->opcode) != 0)) { \
- gen_set_cr1_from_fpscr(ctx); \
- } \
- tcg_temp_free_ptr(rt); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_i32(i32); \
- }
-
-#define GEN_DFP_T_B_Rc(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr rt, rb; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- rt = gen_fprp_ptr(rD(ctx->opcode)); \
- rb = gen_fprp_ptr(rB(ctx->opcode)); \
- gen_helper_##name(cpu_env, rt, rb); \
- if (unlikely(Rc(ctx->opcode) != 0)) { \
- gen_set_cr1_from_fpscr(ctx); \
- } \
- tcg_temp_free_ptr(rt); \
- tcg_temp_free_ptr(rb); \
- }
-
-#define GEN_DFP_T_FPR_I32_Rc(name, fprfld, i32fld) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr rt, rs; \
- TCGv_i32 i32; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_update_nip(ctx, ctx->base.pc_next - 4); \
- rt = gen_fprp_ptr(rD(ctx->opcode)); \
- rs = gen_fprp_ptr(fprfld(ctx->opcode)); \
- i32 = tcg_const_i32(i32fld(ctx->opcode)); \
- gen_helper_##name(cpu_env, rt, rs, i32); \
- if (unlikely(Rc(ctx->opcode) != 0)) { \
- gen_set_cr1_from_fpscr(ctx); \
- } \
- tcg_temp_free_ptr(rt); \
- tcg_temp_free_ptr(rs); \
- tcg_temp_free_i32(i32); \
+#define TRANS_DFP_T_A_B_I32_Rc(NAME, I32FLD) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rt, ra, rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rt = gen_fprp_ptr(a->frt); \
+ ra = gen_fprp_ptr(a->fra); \
+ rb = gen_fprp_ptr(a->frb); \
+ gen_helper_##NAME(tcg_env, rt, ra, rb, \
+ tcg_constant_i32(a->I32FLD)); \
+ if (unlikely(a->rc)) { \
+ gen_set_cr1_from_fpscr(ctx); \
+ } \
+ return true; \
}
-GEN_DFP_T_A_B_Rc(dadd)
-GEN_DFP_T_A_B_Rc(daddq)
-GEN_DFP_T_A_B_Rc(dsub)
-GEN_DFP_T_A_B_Rc(dsubq)
-GEN_DFP_T_A_B_Rc(dmul)
-GEN_DFP_T_A_B_Rc(dmulq)
-GEN_DFP_T_A_B_Rc(ddiv)
-GEN_DFP_T_A_B_Rc(ddivq)
-GEN_DFP_BF_A_B(dcmpu)
-GEN_DFP_BF_A_B(dcmpuq)
-GEN_DFP_BF_A_B(dcmpo)
-GEN_DFP_BF_A_B(dcmpoq)
-GEN_DFP_BF_A_DCM(dtstdc)
-GEN_DFP_BF_A_DCM(dtstdcq)
-GEN_DFP_BF_A_DCM(dtstdg)
-GEN_DFP_BF_A_DCM(dtstdgq)
-GEN_DFP_BF_A_B(dtstex)
-GEN_DFP_BF_A_B(dtstexq)
-GEN_DFP_BF_A_B(dtstsf)
-GEN_DFP_BF_A_B(dtstsfq)
-GEN_DFP_BF_I_B(dtstsfi)
-GEN_DFP_BF_I_B(dtstsfiq)
-GEN_DFP_T_B_U32_U32_Rc(dquai, SIMM5, RMC)
-GEN_DFP_T_B_U32_U32_Rc(dquaiq, SIMM5, RMC)
-GEN_DFP_T_A_B_I32_Rc(dqua, RMC)
-GEN_DFP_T_A_B_I32_Rc(dquaq, RMC)
-GEN_DFP_T_A_B_I32_Rc(drrnd, RMC)
-GEN_DFP_T_A_B_I32_Rc(drrndq, RMC)
-GEN_DFP_T_B_U32_U32_Rc(drintx, FPW, RMC)
-GEN_DFP_T_B_U32_U32_Rc(drintxq, FPW, RMC)
-GEN_DFP_T_B_U32_U32_Rc(drintn, FPW, RMC)
-GEN_DFP_T_B_U32_U32_Rc(drintnq, FPW, RMC)
-GEN_DFP_T_B_Rc(dctdp)
-GEN_DFP_T_B_Rc(dctqpq)
-GEN_DFP_T_B_Rc(drsp)
-GEN_DFP_T_B_Rc(drdpq)
-GEN_DFP_T_B_Rc(dcffix)
-GEN_DFP_T_B_Rc(dcffixq)
-GEN_DFP_T_B_Rc(dctfix)
-GEN_DFP_T_B_Rc(dctfixq)
-GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
-GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
-GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
-GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
-GEN_DFP_T_B_Rc(dxex)
-GEN_DFP_T_B_Rc(dxexq)
-GEN_DFP_T_A_B_Rc(diex)
-GEN_DFP_T_A_B_Rc(diexq)
-GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
-GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
-GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
-GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
-
-#undef GEN_DFP_T_A_B_Rc
-#undef GEN_DFP_BF_A_B
-#undef GEN_DFP_BF_A_DCM
-#undef GEN_DFP_T_B_U32_U32_Rc
-#undef GEN_DFP_T_A_B_I32_Rc
-#undef GEN_DFP_T_B_Rc
-#undef GEN_DFP_T_FPR_I32_Rc
+#define TRANS_DFP_T_B_Rc(NAME) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rt, rb; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rt = gen_fprp_ptr(a->rt); \
+ rb = gen_fprp_ptr(a->rb); \
+ gen_helper_##NAME(tcg_env, rt, rb); \
+ if (unlikely(a->rc)) { \
+ gen_set_cr1_from_fpscr(ctx); \
+ } \
+ return true; \
+}
+
+#define TRANS_DFP_T_FPR_I32_Rc(NAME, FPRFLD, I32FLD) \
+static bool trans_##NAME(DisasContext *ctx, arg_##NAME *a) \
+{ \
+ TCGv_ptr rt, rx; \
+ REQUIRE_INSNS_FLAGS2(ctx, DFP); \
+ REQUIRE_FPU(ctx); \
+ rt = gen_fprp_ptr(a->rt); \
+ rx = gen_fprp_ptr(a->FPRFLD); \
+ gen_helper_##NAME(tcg_env, rt, rx, \
+ tcg_constant_i32(a->I32FLD)); \
+ if (unlikely(a->rc)) { \
+ gen_set_cr1_from_fpscr(ctx); \
+ } \
+ return true; \
+}
+
+TRANS_DFP_T_A_B_Rc(DADD)
+TRANS_DFP_T_A_B_Rc(DADDQ)
+TRANS_DFP_T_A_B_Rc(DSUB)
+TRANS_DFP_T_A_B_Rc(DSUBQ)
+TRANS_DFP_T_A_B_Rc(DMUL)
+TRANS_DFP_T_A_B_Rc(DMULQ)
+TRANS_DFP_T_A_B_Rc(DDIV)
+TRANS_DFP_T_A_B_Rc(DDIVQ)
+TRANS_DFP_BF_A_B(DCMPU)
+TRANS_DFP_BF_A_B(DCMPUQ)
+TRANS_DFP_BF_A_B(DCMPO)
+TRANS_DFP_BF_A_B(DCMPOQ)
+TRANS_DFP_BF_A_DCM(DTSTDC)
+TRANS_DFP_BF_A_DCM(DTSTDCQ)
+TRANS_DFP_BF_A_DCM(DTSTDG)
+TRANS_DFP_BF_A_DCM(DTSTDGQ)
+TRANS_DFP_BF_A_B(DTSTEX)
+TRANS_DFP_BF_A_B(DTSTEXQ)
+TRANS_DFP_BF_A_B(DTSTSF)
+TRANS_DFP_BF_A_B(DTSTSFQ)
+TRANS_DFP_BF_I_B(DTSTSFI)
+TRANS_DFP_BF_I_B(DTSTSFIQ)
+TRANS_DFP_T_B_U32_U32_Rc(DQUAI, te, rmc)
+TRANS_DFP_T_B_U32_U32_Rc(DQUAIQ, te, rmc)
+TRANS_DFP_T_A_B_I32_Rc(DQUA, rmc)
+TRANS_DFP_T_A_B_I32_Rc(DQUAQ, rmc)
+TRANS_DFP_T_A_B_I32_Rc(DRRND, rmc)
+TRANS_DFP_T_A_B_I32_Rc(DRRNDQ, rmc)
+TRANS_DFP_T_B_U32_U32_Rc(DRINTX, r, rmc)
+TRANS_DFP_T_B_U32_U32_Rc(DRINTXQ, r, rmc)
+TRANS_DFP_T_B_U32_U32_Rc(DRINTN, r, rmc)
+TRANS_DFP_T_B_U32_U32_Rc(DRINTNQ, r, rmc)
+TRANS_DFP_T_B_Rc(DCTDP)
+TRANS_DFP_T_B_Rc(DCTQPQ)
+TRANS_DFP_T_B_Rc(DRSP)
+TRANS_DFP_T_B_Rc(DRDPQ)
+TRANS_DFP_T_B_Rc(DCFFIX)
+TRANS_DFP_T_B_Rc(DCFFIXQ)
+TRANS_DFP_T_B_Rc(DCTFIX)
+TRANS_DFP_T_B_Rc(DCTFIXQ)
+TRANS_DFP_T_FPR_I32_Rc(DDEDPD, rb, sp)
+TRANS_DFP_T_FPR_I32_Rc(DDEDPDQ, rb, sp)
+TRANS_DFP_T_FPR_I32_Rc(DENBCD, rb, s)
+TRANS_DFP_T_FPR_I32_Rc(DENBCDQ, rb, s)
+TRANS_DFP_T_B_Rc(DXEX)
+TRANS_DFP_T_B_Rc(DXEXQ)
+TRANS_DFP_T_A_B_Rc(DIEX)
+TRANS_DFP_T_A_B_Rc(DIEXQ)
+TRANS_DFP_T_FPR_I32_Rc(DSCLI, ra, sh)
+TRANS_DFP_T_FPR_I32_Rc(DSCLIQ, ra, sh)
+TRANS_DFP_T_FPR_I32_Rc(DSCRI, ra, sh)
+TRANS_DFP_T_FPR_I32_Rc(DSCRIQ, ra, sh)
+
+static bool trans_DCFFIXQQ(DisasContext *ctx, arg_DCFFIXQQ *a)
+{
+ TCGv_ptr rt, rb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, DFP);
+ REQUIRE_FPU(ctx);
+ REQUIRE_VECTOR(ctx);
+
+ rt = gen_fprp_ptr(a->frtp);
+ rb = gen_avr_ptr(a->vrb);
+ gen_helper_DCFFIXQQ(tcg_env, rt, rb);
+
+ return true;
+}
+
+static bool trans_DCTFIXQQ(DisasContext *ctx, arg_DCTFIXQQ *a)
+{
+ TCGv_ptr rt, rb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, DFP);
+ REQUIRE_FPU(ctx);
+ REQUIRE_VECTOR(ctx);
+
+ rt = gen_avr_ptr(a->vrt);
+ rb = gen_fprp_ptr(a->frbp);
+ gen_helper_DCTFIXQQ(tcg_env, rt, rb);
+
+ return true;
+}
diff --git a/target/ppc/translate/dfp-ops.c.inc b/target/ppc/translate/dfp-ops.c.inc
deleted file mode 100644
index 6ef38e5712..0000000000
--- a/target/ppc/translate/dfp-ops.c.inc
+++ /dev/null
@@ -1,165 +0,0 @@
-#define _GEN_DFP_LONG(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_DFP)
-
-#define _GEN_DFP_LONG_300(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3B, op1, op2, mask, PPC_NONE, PPC2_ISA300)
-
-#define _GEN_DFP_LONGx2(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
-
-#define _GEN_DFP_LONGx4(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3B, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3B, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3B, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3B, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
-
-#define _GEN_DFP_QUAD(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_DFP)
-
-#define _GEN_DFP_QUAD_300(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3F, op1, op2, mask, PPC_NONE, PPC2_ISA300)
-
-#define _GEN_DFP_QUADx2(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP)
-
-#define _GEN_DFP_QUADx4(name, op1, op2, mask) \
-GEN_HANDLER_E(name, 0x3F, op1, 0x00 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3F, op1, 0x08 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3F, op1, 0x10 | op2, mask, PPC_NONE, PPC2_DFP), \
-GEN_HANDLER_E(name, 0x3F, op1, 0x18 | op2, mask, PPC_NONE, PPC2_DFP)
-
-#define GEN_DFP_T_A_B_Rc(name, op1, op2) \
-_GEN_DFP_LONG(name, op1, op2, 0x00000000)
-
-#define GEN_DFP_Tp_Ap_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x00210800)
-
-#define GEN_DFP_Tp_A_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x00200800)
-
-#define GEN_DFP_T_B_Rc(name, op1, op2) \
-_GEN_DFP_LONG(name, op1, op2, 0x001F0000)
-
-#define GEN_DFP_Tp_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x003F0800)
-
-#define GEN_DFP_Tp_B_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x003F0000)
-
-#define GEN_DFP_T_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x001F0800)
-
-#define GEN_DFP_BF_A_B(name, op1, op2) \
-_GEN_DFP_LONG(name, op1, op2, 0x00000001)
-
-#define GEN_DFP_BF_A_B_300(name, op1, op2) \
-_GEN_DFP_LONG_300(name, op1, op2, 0x00400001)
-
-#define GEN_DFP_BF_Ap_Bp(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x00610801)
-
-#define GEN_DFP_BF_A_Bp(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x00600801)
-
-#define GEN_DFP_BF_A_Bp_300(name, op1, op2) \
-_GEN_DFP_QUAD_300(name, op1, op2, 0x00400001)
-
-#define GEN_DFP_BF_A_DCM(name, op1, op2) \
-_GEN_DFP_LONGx2(name, op1, op2, 0x00600001)
-
-#define GEN_DFP_BF_Ap_DCM(name, op1, op2) \
-_GEN_DFP_QUADx2(name, op1, op2, 0x00610001)
-
-#define GEN_DFP_T_A_B_RMC_Rc(name, op1, op2) \
-_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
-
-#define GEN_DFP_Tp_Ap_Bp_RMC_Rc(name, op1, op2) \
-_GEN_DFP_QUADx4(name, op1, op2, 0x02010800)
-
-#define GEN_DFP_Tp_A_Bp_RMC_Rc(name, op1, op2) \
-_GEN_DFP_QUADx4(name, op1, op2, 0x02000800)
-
-#define GEN_DFP_TE_T_B_RMC_Rc(name, op1, op2) \
-_GEN_DFP_LONGx4(name, op1, op2, 0x00000000)
-
-#define GEN_DFP_TE_Tp_Bp_RMC_Rc(name, op1, op2) \
-_GEN_DFP_QUADx4(name, op1, op2, 0x00200800)
-
-#define GEN_DFP_R_T_B_RMC_Rc(name, op1, op2) \
-_GEN_DFP_LONGx4(name, op1, op2, 0x001E0000)
-
-#define GEN_DFP_R_Tp_Bp_RMC_Rc(name, op1, op2) \
-_GEN_DFP_QUADx4(name, op1, op2, 0x003E0800)
-
-#define GEN_DFP_SP_T_B_Rc(name, op1, op2) \
-_GEN_DFP_LONG(name, op1, op2, 0x00070000)
-
-#define GEN_DFP_SP_Tp_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x00270800)
-
-#define GEN_DFP_S_T_B_Rc(name, op1, op2) \
-_GEN_DFP_LONG(name, op1, op2, 0x000F0000)
-
-#define GEN_DFP_S_Tp_Bp_Rc(name, op1, op2) \
-_GEN_DFP_QUAD(name, op1, op2, 0x002F0800)
-
-#define GEN_DFP_T_A_SH_Rc(name, op1, op2) \
-_GEN_DFP_LONGx2(name, op1, op2, 0x00000000)
-
-#define GEN_DFP_Tp_Ap_SH_Rc(name, op1, op2) \
-_GEN_DFP_QUADx2(name, op1, op2, 0x00210000)
-
-GEN_DFP_T_A_B_Rc(dadd, 0x02, 0x00),
-GEN_DFP_Tp_Ap_Bp_Rc(daddq, 0x02, 0x00),
-GEN_DFP_T_A_B_Rc(dsub, 0x02, 0x10),
-GEN_DFP_Tp_Ap_Bp_Rc(dsubq, 0x02, 0x10),
-GEN_DFP_T_A_B_Rc(dmul, 0x02, 0x01),
-GEN_DFP_Tp_Ap_Bp_Rc(dmulq, 0x02, 0x01),
-GEN_DFP_T_A_B_Rc(ddiv, 0x02, 0x11),
-GEN_DFP_Tp_Ap_Bp_Rc(ddivq, 0x02, 0x11),
-GEN_DFP_BF_A_B(dcmpu, 0x02, 0x14),
-GEN_DFP_BF_Ap_Bp(dcmpuq, 0x02, 0x14),
-GEN_DFP_BF_A_B(dcmpo, 0x02, 0x04),
-GEN_DFP_BF_Ap_Bp(dcmpoq, 0x02, 0x04),
-GEN_DFP_BF_A_DCM(dtstdc, 0x02, 0x06),
-GEN_DFP_BF_Ap_DCM(dtstdcq, 0x02, 0x06),
-GEN_DFP_BF_A_DCM(dtstdg, 0x02, 0x07),
-GEN_DFP_BF_Ap_DCM(dtstdgq, 0x02, 0x07),
-GEN_DFP_BF_A_B(dtstex, 0x02, 0x05),
-GEN_DFP_BF_Ap_Bp(dtstexq, 0x02, 0x05),
-GEN_DFP_BF_A_B(dtstsf, 0x02, 0x15),
-GEN_DFP_BF_A_Bp(dtstsfq, 0x02, 0x15),
-GEN_DFP_BF_A_B_300(dtstsfi, 0x03, 0x15),
-GEN_DFP_BF_A_Bp_300(dtstsfiq, 0x03, 0x15),
-GEN_DFP_TE_T_B_RMC_Rc(dquai, 0x03, 0x02),
-GEN_DFP_TE_Tp_Bp_RMC_Rc(dquaiq, 0x03, 0x02),
-GEN_DFP_T_A_B_RMC_Rc(dqua, 0x03, 0x00),
-GEN_DFP_Tp_Ap_Bp_RMC_Rc(dquaq, 0x03, 0x00),
-GEN_DFP_T_A_B_RMC_Rc(drrnd, 0x03, 0x01),
-GEN_DFP_Tp_A_Bp_RMC_Rc(drrndq, 0x03, 0x01),
-GEN_DFP_R_T_B_RMC_Rc(drintx, 0x03, 0x03),
-GEN_DFP_R_Tp_Bp_RMC_Rc(drintxq, 0x03, 0x03),
-GEN_DFP_R_T_B_RMC_Rc(drintn, 0x03, 0x07),
-GEN_DFP_R_Tp_Bp_RMC_Rc(drintnq, 0x03, 0x07),
-GEN_DFP_T_B_Rc(dctdp, 0x02, 0x08),
-GEN_DFP_Tp_B_Rc(dctqpq, 0x02, 0x08),
-GEN_DFP_T_B_Rc(drsp, 0x02, 0x18),
-GEN_DFP_Tp_Bp_Rc(drdpq, 0x02, 0x18),
-GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19),
-GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19),
-GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
-GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
-GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
-GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
-GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
-GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
-GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
-GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
-GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
-GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
-GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
-GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
-GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
-GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
diff --git a/target/ppc/translate/fixedpoint-impl.c.inc b/target/ppc/translate/fixedpoint-impl.c.inc
index 2e2518ee15..0c66465d96 100644
--- a/target/ppc/translate/fixedpoint-impl.c.inc
+++ b/target/ppc/translate/fixedpoint-impl.c.inc
@@ -18,25 +18,6 @@
*/
/*
- * Incorporate CIA into the constant when R=1.
- * Validate that when R=1, RA=0.
- */
-static bool resolve_PLS_D(DisasContext *ctx, arg_D *d, arg_PLS_D *a)
-{
- d->rt = a->rt;
- d->ra = a->ra;
- d->si = a->si;
- if (a->r) {
- if (unlikely(a->ra != 0)) {
- gen_invalid(ctx);
- return false;
- }
- d->si += ctx->cia;
- }
- return true;
-}
-
-/*
* Fixed-Point Load/Store Instructions
*/
@@ -51,15 +32,7 @@ static bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
}
gen_set_access_type(ctx, ACCESS_INT);
- ea = tcg_temp_new();
- if (ra) {
- tcg_gen_add_tl(ea, cpu_gpr[ra], displ);
- } else {
- tcg_gen_mov_tl(ea, displ);
- }
- if (NARROW_MODE(ctx)) {
- tcg_gen_ext32u_tl(ea, ea);
- }
+ ea = do_ea_calc(ctx, ra, displ);
mop ^= ctx->default_tcg_memop_mask;
if (store) {
tcg_gen_qemu_st_tl(cpu_gpr[rt], ea, ctx->mem_idx, mop);
@@ -69,8 +42,6 @@ static bool do_ldst(DisasContext *ctx, int rt, int ra, TCGv displ, bool update,
if (update) {
tcg_gen_mov_tl(cpu_gpr[ra], ea);
}
- tcg_temp_free(ea);
-
return true;
}
@@ -96,6 +67,66 @@ static bool do_ldst_X(DisasContext *ctx, arg_X *a, bool update,
return do_ldst(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, mop);
}
+static bool do_ldst_quad(DisasContext *ctx, arg_D *a, bool store, bool prefixed)
+{
+#if defined(TARGET_PPC64)
+ TCGv ea;
+ TCGv_i64 lo, hi;
+ TCGv_i128 t16;
+
+ REQUIRE_INSNS_FLAGS(ctx, 64BX);
+
+ if (!prefixed && !(ctx->insns_flags2 & PPC2_LSQ_ISA207)) {
+ /* lq and stq were privileged prior to V. 2.07 */
+ REQUIRE_SV(ctx);
+
+ if (ctx->le_mode) {
+ gen_align_no_le(ctx);
+ return true;
+ }
+ }
+
+ if (!store && unlikely(a->ra == a->rt)) {
+ gen_invalid(ctx);
+ return true;
+ }
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->si));
+
+ if (ctx->le_mode && prefixed) {
+ lo = cpu_gpr[a->rt];
+ hi = cpu_gpr[a->rt + 1];
+ } else {
+ lo = cpu_gpr[a->rt + 1];
+ hi = cpu_gpr[a->rt];
+ }
+ t16 = tcg_temp_new_i128();
+
+ if (store) {
+ tcg_gen_concat_i64_i128(t16, lo, hi);
+ tcg_gen_qemu_st_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
+ } else {
+ tcg_gen_qemu_ld_i128(t16, ea, ctx->mem_idx, DEF_MEMOP(MO_128));
+ tcg_gen_extr_i128_i64(lo, hi, t16);
+ }
+#else
+ qemu_build_not_reached();
+#endif
+
+ return true;
+}
+
+static bool do_ldst_quad_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
+{
+ arg_D d;
+ if (!resolve_PLS_D(ctx, &d, a)) {
+ return true;
+ }
+
+ return do_ldst_quad(ctx, &d, store, true);
+}
+
/* Load Byte and Zero */
TRANS(LBZ, do_ldst_D, false, false, MO_UB)
TRANS(LBZX, do_ldst_X, false, false, MO_UB)
@@ -131,11 +162,15 @@ TRANS64(LWAUX, do_ldst_X, true, false, MO_SL)
TRANS64(PLWA, do_ldst_PLS_D, false, false, MO_SL)
/* Load Doubleword */
-TRANS64(LD, do_ldst_D, false, false, MO_Q)
-TRANS64(LDX, do_ldst_X, false, false, MO_Q)
-TRANS64(LDU, do_ldst_D, true, false, MO_Q)
-TRANS64(LDUX, do_ldst_X, true, false, MO_Q)
-TRANS64(PLD, do_ldst_PLS_D, false, false, MO_Q)
+TRANS64(LD, do_ldst_D, false, false, MO_UQ)
+TRANS64(LDX, do_ldst_X, false, false, MO_UQ)
+TRANS64(LDU, do_ldst_D, true, false, MO_UQ)
+TRANS64(LDUX, do_ldst_X, true, false, MO_UQ)
+TRANS64(PLD, do_ldst_PLS_D, false, false, MO_UQ)
+
+/* Load Quadword */
+TRANS64(LQ, do_ldst_quad, false, false);
+TRANS64(PLQ, do_ldst_quad_PLS_D, false);
/* Store Byte */
TRANS(STB, do_ldst_D, false, true, MO_UB)
@@ -159,11 +194,15 @@ TRANS(STWUX, do_ldst_X, true, true, MO_UL)
TRANS(PSTW, do_ldst_PLS_D, false, true, MO_UL)
/* Store Doubleword */
-TRANS64(STD, do_ldst_D, false, true, MO_Q)
-TRANS64(STDX, do_ldst_X, false, true, MO_Q)
-TRANS64(STDU, do_ldst_D, true, true, MO_Q)
-TRANS64(STDUX, do_ldst_X, true, true, MO_Q)
-TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_Q)
+TRANS64(STD, do_ldst_D, false, true, MO_UQ)
+TRANS64(STDX, do_ldst_X, false, true, MO_UQ)
+TRANS64(STDU, do_ldst_D, true, true, MO_UQ)
+TRANS64(STDUX, do_ldst_X, true, true, MO_UQ)
+TRANS64(PSTD, do_ldst_PLS_D, false, true, MO_UQ)
+
+/* Store Quadword */
+TRANS64(STQ, do_ldst_quad, true, false);
+TRANS64(PSTQ, do_ldst_quad_PLS_D, true);
/*
* Fixed-Point Compare Instructions
@@ -286,6 +325,76 @@ static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
return true;
}
+static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ cpu_ov, cpu_ov32, true, true, false, false);
+ return true;
+}
+
+static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
+ bool compute_ov, bool compute_rc0)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
+ tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
+ add_ca, compute_ca, compute_ov, compute_rc0);
+ return true;
+}
+
+static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
+ bool compute_ca)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
+ bool add_ca, bool compute_ca)
+{
+ gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
+ cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+TRANS(ADD, do_add_XO, false, false);
+TRANS(ADDC, do_add_XO, false, true);
+TRANS(ADDE, do_add_XO, true, true);
+TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
+TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
+TRANS(ADDIC, do_add_D, false, true, false, false);
+TRANS(ADDIC_, do_add_D, false, true, false, true);
+
+static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
+ tcg_constant_tl(a->si), false, true, false, false);
+ return true;
+}
+
+static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
+ bool compute_ca)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
+ add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
+ bool add_ca, bool compute_ca)
+{
+ gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
+ add_ca, compute_ca, a->oe, a->rc);
+ return true;
+}
+
+TRANS(SUBF, do_subf_XO, false, false)
+TRANS(SUBFC, do_subf_XO, false, true)
+TRANS(SUBFE, do_subf_XO, true, true)
+TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
+TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
+
static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
{
gen_invalid(ctx);
@@ -303,15 +412,15 @@ static bool do_set_bool_cond(DisasContext *ctx, arg_X_bi *a, bool neg, bool rev)
uint32_t mask = 0x08 >> (a->bi & 0x03);
TCGCond cond = rev ? TCG_COND_EQ : TCG_COND_NE;
TCGv temp = tcg_temp_new();
+ TCGv zero = tcg_constant_tl(0);
tcg_gen_extu_i32_tl(temp, cpu_crf[a->bi >> 2]);
tcg_gen_andi_tl(temp, temp, mask);
- tcg_gen_setcondi_tl(cond, cpu_gpr[a->rt], temp, 0);
if (neg) {
- tcg_gen_neg_tl(cpu_gpr[a->rt], cpu_gpr[a->rt]);
+ tcg_gen_negsetcond_tl(cond, cpu_gpr[a->rt], temp, zero);
+ } else {
+ tcg_gen_setcond_tl(cond, cpu_gpr[a->rt], temp, zero);
}
- tcg_temp_free(temp);
-
return true;
}
@@ -325,9 +434,164 @@ static bool trans_CFUGED(DisasContext *ctx, arg_X *a)
REQUIRE_64BIT(ctx);
REQUIRE_INSNS_FLAGS2(ctx, ISA310);
#if defined(TARGET_PPC64)
- gen_helper_cfuged(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
+ gen_helper_CFUGED(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static void do_cntzdm(TCGv_i64 dst, TCGv_i64 src, TCGv_i64 mask, int64_t trail)
+{
+ TCGv_i64 t0, t1;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ tcg_gen_and_i64(t0, src, mask);
+ if (trail) {
+ tcg_gen_ctzi_i64(t0, t0, -1);
+ } else {
+ tcg_gen_clzi_i64(t0, t0, -1);
+ }
+
+ tcg_gen_setcondi_i64(TCG_COND_NE, t1, t0, -1);
+ tcg_gen_andi_i64(t0, t0, 63);
+ tcg_gen_xori_i64(t0, t0, 63);
+ if (trail) {
+ tcg_gen_shl_i64(t0, mask, t0);
+ tcg_gen_shl_i64(t0, t0, t1);
+ } else {
+ tcg_gen_shr_i64(t0, mask, t0);
+ tcg_gen_shr_i64(t0, t0, t1);
+ }
+
+ tcg_gen_ctpop_i64(dst, t0);
+}
+
+static bool trans_CNTLZDM(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+#if defined(TARGET_PPC64)
+ do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], false);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_CNTTZDM(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+#if defined(TARGET_PPC64)
+ do_cntzdm(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb], true);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_PDEPD(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+#if defined(TARGET_PPC64)
+ gen_helper_PDEPD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_PEXTD(DisasContext *ctx, arg_X *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+#if defined(TARGET_PPC64)
+ gen_helper_PEXTD(cpu_gpr[a->ra], cpu_gpr[a->rt], cpu_gpr[a->rb]);
#else
qemu_build_not_reached();
#endif
return true;
}
+
+static bool trans_ADDG6S(DisasContext *ctx, arg_X *a)
+{
+ const target_ulong carry_bits = (target_ulong)-1 / 0xf;
+ TCGv in1, in2, carryl, carryh, tmp;
+ TCGv zero = tcg_constant_tl(0);
+
+ REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+
+ in1 = cpu_gpr[a->ra];
+ in2 = cpu_gpr[a->rb];
+ tmp = tcg_temp_new();
+ carryl = tcg_temp_new();
+ carryh = tcg_temp_new();
+
+ /* Addition with carry. */
+ tcg_gen_add2_tl(carryl, carryh, in1, zero, in2, zero);
+ /* Addition without carry. */
+ tcg_gen_xor_tl(tmp, in1, in2);
+ /* Difference between the two is carry in to each bit. */
+ tcg_gen_xor_tl(carryl, carryl, tmp);
+
+ /*
+ * The carry-out that we're looking for is the carry-in to
+ * the next nibble. Shift the double-word down one nibble,
+ * which puts all of the bits back into one word.
+ */
+ tcg_gen_extract2_tl(carryl, carryl, carryh, 4);
+
+ /* Invert, isolate the carry bits, and produce 6's. */
+ tcg_gen_andc_tl(carryl, tcg_constant_tl(carry_bits), carryl);
+ tcg_gen_muli_tl(cpu_gpr[a->rt], carryl, 6);
+ return true;
+}
+
+static bool trans_CDTBCD(DisasContext *ctx, arg_X_sa *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+ gen_helper_CDTBCD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
+ return true;
+}
+
+static bool trans_CBCDTD(DisasContext *ctx, arg_X_sa *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, BCDA_ISA206);
+ gen_helper_CBCDTD(cpu_gpr[a->ra], cpu_gpr[a->rs]);
+ return true;
+}
+
+static bool do_hash(DisasContext *ctx, arg_X *a, bool priv,
+ void (*helper)(TCGv_ptr, TCGv, TCGv, TCGv))
+{
+ TCGv ea;
+
+ if (!(ctx->insns_flags2 & PPC2_ISA310)) {
+ /* if version is before v3.1, this operation is a nop */
+ return true;
+ }
+
+ if (priv) {
+ /* if instruction is privileged but the context is in user space */
+ REQUIRE_SV(ctx);
+ }
+
+ if (unlikely(a->ra == 0)) {
+ /* if RA=0, the instruction form is invalid */
+ gen_invalid(ctx);
+ return true;
+ }
+
+ ea = do_ea_calc(ctx, a->ra, tcg_constant_tl(a->rt));
+ helper(tcg_env, ea, cpu_gpr[a->ra], cpu_gpr[a->rb]);
+ return true;
+}
+
+TRANS(HASHST, do_hash, false, gen_helper_HASHST)
+TRANS(HASHCHK, do_hash, false, gen_helper_HASHCHK)
+TRANS(HASHSTP, do_hash, true, gen_helper_HASHSTP)
+TRANS(HASHCHKP, do_hash, true, gen_helper_HASHCHKP)
diff --git a/target/ppc/translate/fp-impl.c.inc b/target/ppc/translate/fp-impl.c.inc
index 9f7868ee28..189cd8c979 100644
--- a/target/ppc/translate/fp-impl.c.inc
+++ b/target/ppc/translate/fp-impl.c.inc
@@ -6,13 +6,13 @@
static inline void gen_reset_fpstatus(void)
{
- gen_helper_reset_fpstatus(cpu_env);
+ gen_helper_reset_fpstatus(tcg_env);
}
static inline void gen_compute_fprf_float64(TCGv_i64 arg)
{
- gen_helper_compute_fprf_float64(cpu_env, arg);
- gen_helper_float_check_status(cpu_env);
+ gen_helper_compute_fprf_float64(tcg_env, arg);
+ gen_helper_float_check_status(tcg_env);
}
#if defined(TARGET_PPC64)
@@ -21,7 +21,6 @@ static void gen_set_cr1_from_fpscr(DisasContext *ctx)
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(tmp, cpu_fpscr);
tcg_gen_shri_i32(cpu_crf[1], tmp, 28);
- tcg_temp_free_i32(tmp);
}
#else
static void gen_set_cr1_from_fpscr(DisasContext *ctx)
@@ -31,7 +30,7 @@ static void gen_set_cr1_from_fpscr(DisasContext *ctx)
#endif
/*** Floating-Point arithmetic ***/
-#define _GEN_FLOAT_ACB(name, op, op1, op2, isfloat, set_fprf, type) \
+#define _GEN_FLOAT_ACB(name, op1, op2, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
TCGv_i64 t0; \
@@ -50,10 +49,7 @@ static void gen_f##name(DisasContext *ctx) \
get_fpr(t0, rA(ctx->opcode)); \
get_fpr(t1, rC(ctx->opcode)); \
get_fpr(t2, rB(ctx->opcode)); \
- gen_helper_f##op(t3, cpu_env, t0, t1, t2); \
- if (isfloat) { \
- gen_helper_frsp(t3, cpu_env, t3); \
- } \
+ gen_helper_f##name(t3, tcg_env, t0, t1, t2); \
set_fpr(rD(ctx->opcode), t3); \
if (set_fprf) { \
gen_compute_fprf_float64(t3); \
@@ -61,17 +57,13 @@ static void gen_f##name(DisasContext *ctx) \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
- tcg_temp_free_i64(t3); \
}
#define GEN_FLOAT_ACB(name, op2, set_fprf, type) \
-_GEN_FLOAT_ACB(name, name, 0x3F, op2, 0, set_fprf, type); \
-_GEN_FLOAT_ACB(name##s, name, 0x3B, op2, 1, set_fprf, type);
+_GEN_FLOAT_ACB(name, 0x3F, op2, set_fprf, type); \
+_GEN_FLOAT_ACB(name##s, 0x3B, op2, set_fprf, type);
-#define _GEN_FLOAT_AB(name, op, op1, op2, inval, isfloat, set_fprf, type) \
+#define _GEN_FLOAT_AB(name, op1, op2, inval, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
TCGv_i64 t0; \
@@ -87,10 +79,7 @@ static void gen_f##name(DisasContext *ctx) \
gen_reset_fpstatus(); \
get_fpr(t0, rA(ctx->opcode)); \
get_fpr(t1, rB(ctx->opcode)); \
- gen_helper_f##op(t2, cpu_env, t0, t1); \
- if (isfloat) { \
- gen_helper_frsp(t2, cpu_env, t2); \
- } \
+ gen_helper_f##name(t2, tcg_env, t0, t1); \
set_fpr(rD(ctx->opcode), t2); \
if (set_fprf) { \
gen_compute_fprf_float64(t2); \
@@ -98,15 +87,12 @@ static void gen_f##name(DisasContext *ctx) \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
}
#define GEN_FLOAT_AB(name, op2, inval, set_fprf, type) \
-_GEN_FLOAT_AB(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
-_GEN_FLOAT_AB(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
+_GEN_FLOAT_AB(name, 0x3F, op2, inval, set_fprf, type); \
+_GEN_FLOAT_AB(name##s, 0x3B, op2, inval, set_fprf, type);
-#define _GEN_FLOAT_AC(name, op, op1, op2, inval, isfloat, set_fprf, type) \
+#define _GEN_FLOAT_AC(name, op1, op2, inval, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
{ \
TCGv_i64 t0; \
@@ -122,10 +108,7 @@ static void gen_f##name(DisasContext *ctx) \
gen_reset_fpstatus(); \
get_fpr(t0, rA(ctx->opcode)); \
get_fpr(t1, rC(ctx->opcode)); \
- gen_helper_f##op(t2, cpu_env, t0, t1); \
- if (isfloat) { \
- gen_helper_frsp(t2, cpu_env, t2); \
- } \
+ gen_helper_f##name(t2, tcg_env, t0, t1); \
set_fpr(rD(ctx->opcode), t2); \
if (set_fprf) { \
gen_compute_fprf_float64(t2); \
@@ -133,13 +116,10 @@ static void gen_f##name(DisasContext *ctx) \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
}
#define GEN_FLOAT_AC(name, op2, inval, set_fprf, type) \
-_GEN_FLOAT_AC(name, name, 0x3F, op2, inval, 0, set_fprf, type); \
-_GEN_FLOAT_AC(name##s, name, 0x3B, op2, inval, 1, set_fprf, type);
+_GEN_FLOAT_AC(name, 0x3F, op2, inval, set_fprf, type); \
+_GEN_FLOAT_AC(name##s, 0x3B, op2, inval, set_fprf, type);
#define GEN_FLOAT_B(name, op2, op3, set_fprf, type) \
static void gen_f##name(DisasContext *ctx) \
@@ -154,16 +134,15 @@ static void gen_f##name(DisasContext *ctx) \
t1 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
get_fpr(t0, rB(ctx->opcode)); \
- gen_helper_f##name(t1, cpu_env, t0); \
+ gen_helper_f##name(t1, tcg_env, t0); \
set_fpr(rD(ctx->opcode), t1); \
if (set_fprf) { \
- gen_compute_fprf_float64(t1); \
+ gen_helper_compute_fprf_float64(tcg_env, t1); \
} \
+ gen_helper_float_check_status(tcg_env); \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
}
#define GEN_FLOAT_BS(name, op1, op2, set_fprf, type) \
@@ -179,7 +158,7 @@ static void gen_f##name(DisasContext *ctx) \
t1 = tcg_temp_new_i64(); \
gen_reset_fpstatus(); \
get_fpr(t0, rB(ctx->opcode)); \
- gen_helper_f##name(t1, cpu_env, t0); \
+ gen_helper_f##name(t1, tcg_env, t0); \
set_fpr(rD(ctx->opcode), t1); \
if (set_fprf) { \
gen_compute_fprf_float64(t1); \
@@ -187,8 +166,6 @@ static void gen_f##name(DisasContext *ctx) \
if (unlikely(Rc(ctx->opcode) != 0)) { \
gen_set_cr1_from_fpscr(ctx); \
} \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
}
/* fadd - fadds */
@@ -220,69 +197,66 @@ static void gen_frsqrtes(DisasContext *ctx)
t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
get_fpr(t0, rB(ctx->opcode));
- gen_helper_frsqrte(t1, cpu_env, t0);
- gen_helper_frsp(t1, cpu_env, t1);
+ gen_helper_frsqrtes(t1, tcg_env, t0);
set_fpr(rD(ctx->opcode), t1);
gen_compute_fprf_float64(t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
-/* fsel */
-_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL);
-/* fsub - fsubs */
-GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
-/* Optional: */
-
-/* fsqrt */
-static void gen_fsqrt(DisasContext *ctx)
+static bool trans_FSEL(DisasContext *ctx, arg_A *a)
{
- TCGv_i64 t0;
- TCGv_i64 t1;
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
+ TCGv_i64 t0, t1, t2;
+
+ REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSEL);
+ REQUIRE_FPU(ctx);
+
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
- gen_reset_fpstatus();
- get_fpr(t0, rB(ctx->opcode));
- gen_helper_fsqrt(t1, cpu_env, t0);
- set_fpr(rD(ctx->opcode), t1);
- gen_compute_fprf_float64(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
+ t2 = tcg_temp_new_i64();
+
+ get_fpr(t0, a->fra);
+ get_fpr(t1, a->frb);
+ get_fpr(t2, a->frc);
+
+ gen_helper_FSEL(t0, t0, t1, t2);
+ set_fpr(a->frt, t0);
+ if (a->rc) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
+ return true;
}
-static void gen_fsqrts(DisasContext *ctx)
+/* fsub - fsubs */
+GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT);
+/* Optional: */
+
+static bool do_helper_fsqrt(DisasContext *ctx, arg_A_tb *a,
+ void (*helper)(TCGv_i64, TCGv_ptr, TCGv_i64))
{
- TCGv_i64 t0;
- TCGv_i64 t1;
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
+ TCGv_i64 t0, t1;
+
+ REQUIRE_INSNS_FLAGS(ctx, FLOAT_FSQRT);
+ REQUIRE_FPU(ctx);
+
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
+
gen_reset_fpstatus();
- get_fpr(t0, rB(ctx->opcode));
- gen_helper_fsqrt(t1, cpu_env, t0);
- gen_helper_frsp(t1, cpu_env, t1);
- set_fpr(rD(ctx->opcode), t1);
+ get_fpr(t0, a->frb);
+ helper(t1, tcg_env, t0);
+ set_fpr(a->frt, t1);
gen_compute_fprf_float64(t1);
- if (unlikely(Rc(ctx->opcode) != 0)) {
+ if (unlikely(a->rc != 0)) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
+ return true;
}
+TRANS(FSQRT, do_helper_fsqrt, gen_helper_FSQRT);
+TRANS(FSQRTS, do_helper_fsqrt, gen_helper_FSQRTS);
+
/*** Floating-Point multiply-and-add ***/
/* fmadd - fmadds */
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT);
@@ -343,8 +317,6 @@ static void gen_ftdiv(DisasContext *ctx)
get_fpr(t0, rA(ctx->opcode));
get_fpr(t1, rB(ctx->opcode));
gen_helper_ftdiv(cpu_crf[crfD(ctx->opcode)], t0, t1);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
static void gen_ftsqrt(DisasContext *ctx)
@@ -357,7 +329,6 @@ static void gen_ftsqrt(DisasContext *ctx)
t0 = tcg_temp_new_i64();
get_fpr(t0, rB(ctx->opcode));
gen_helper_ftsqrt(cpu_crf[crfD(ctx->opcode)], t0);
- tcg_temp_free_i64(t0);
}
@@ -377,14 +348,11 @@ static void gen_fcmpo(DisasContext *ctx)
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
- crf = tcg_const_i32(crfD(ctx->opcode));
+ crf = tcg_constant_i32(crfD(ctx->opcode));
get_fpr(t0, rA(ctx->opcode));
get_fpr(t1, rB(ctx->opcode));
- gen_helper_fcmpo(cpu_env, t0, t1, crf);
- tcg_temp_free_i32(crf);
- gen_helper_float_check_status(cpu_env);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
+ gen_helper_fcmpo(tcg_env, t0, t1, crf);
+ gen_helper_float_check_status(tcg_env);
}
/* fcmpu */
@@ -400,14 +368,11 @@ static void gen_fcmpu(DisasContext *ctx)
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
gen_reset_fpstatus();
- crf = tcg_const_i32(crfD(ctx->opcode));
+ crf = tcg_constant_i32(crfD(ctx->opcode));
get_fpr(t0, rA(ctx->opcode));
get_fpr(t1, rB(ctx->opcode));
- gen_helper_fcmpu(cpu_env, t0, t1, crf);
- tcg_temp_free_i32(crf);
- gen_helper_float_check_status(cpu_env);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
+ gen_helper_fcmpu(tcg_env, t0, t1, crf);
+ gen_helper_float_check_status(tcg_env);
}
/*** Floating-point move ***/
@@ -429,8 +394,6 @@ static void gen_fabs(DisasContext *ctx)
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
/* fmr - fmr. */
@@ -448,7 +411,6 @@ static void gen_fmr(DisasContext *ctx)
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
}
/* fnabs */
@@ -469,8 +431,6 @@ static void gen_fnabs(DisasContext *ctx)
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
/* fneg */
@@ -491,8 +451,6 @@ static void gen_fneg(DisasContext *ctx)
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
/* fcpsgn: PowerPC 2.05 specification */
@@ -516,9 +474,6 @@ static void gen_fcpsgn(DisasContext *ctx)
if (unlikely(Rc(ctx->opcode))) {
gen_set_cr1_from_fpscr(ctx);
}
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
}
static void gen_fmrgew(DisasContext *ctx)
@@ -538,9 +493,6 @@ static void gen_fmrgew(DisasContext *ctx)
get_fpr(t0, rA(ctx->opcode));
tcg_gen_deposit_i64(t1, t0, b0, 0, 32);
set_fpr(rD(ctx->opcode), t1);
- tcg_temp_free_i64(b0);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
static void gen_fmrgow(DisasContext *ctx)
@@ -559,9 +511,6 @@ static void gen_fmrgow(DisasContext *ctx)
get_fpr(t1, rA(ctx->opcode));
tcg_gen_deposit_i64(t2, t0, t1, 32, 32);
set_fpr(rD(ctx->opcode), t2);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(t2);
}
/*** Floating-Point status & ctrl register ***/
@@ -587,153 +536,147 @@ static void gen_mcrfs(DisasContext *ctx)
tcg_gen_trunc_tl_i32(cpu_crf[crfD(ctx->opcode)], tmp);
tcg_gen_andi_i32(cpu_crf[crfD(ctx->opcode)], cpu_crf[crfD(ctx->opcode)],
0xf);
- tcg_temp_free(tmp);
tcg_gen_extu_tl_i64(tnew_fpscr, cpu_fpscr);
/* Only the exception bits (including FX) should be cleared if read */
tcg_gen_andi_i64(tnew_fpscr, tnew_fpscr,
~((0xF << shift) & FP_EX_CLEAR_BITS));
/* FEX and VX need to be updated, so don't set fpscr directly */
- tmask = tcg_const_i32(1 << nibble);
- gen_helper_store_fpscr(cpu_env, tnew_fpscr, tmask);
- tcg_temp_free_i32(tmask);
- tcg_temp_free_i64(tnew_fpscr);
+ tmask = tcg_constant_i32(1 << nibble);
+ gen_helper_store_fpscr(tcg_env, tnew_fpscr, tmask);
}
-/* mffs */
-static void gen_mffs(DisasContext *ctx)
+static TCGv_i64 place_from_fpscr(int rt, uint64_t mask)
{
- TCGv_i64 t0;
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
- t0 = tcg_temp_new_i64();
- gen_reset_fpstatus();
- tcg_gen_extu_tl_i64(t0, cpu_fpscr);
- set_fpr(rD(ctx->opcode), t0);
- if (unlikely(Rc(ctx->opcode))) {
- gen_set_cr1_from_fpscr(ctx);
- }
- tcg_temp_free_i64(t0);
+ TCGv_i64 fpscr = tcg_temp_new_i64();
+ TCGv_i64 fpscr_masked = tcg_temp_new_i64();
+
+ tcg_gen_extu_tl_i64(fpscr, cpu_fpscr);
+ tcg_gen_andi_i64(fpscr_masked, fpscr, mask);
+ set_fpr(rt, fpscr_masked);
+
+ return fpscr;
}
-/* mffsl */
-static void gen_mffsl(DisasContext *ctx)
+static void store_fpscr_masked(TCGv_i64 fpscr, uint64_t clear_mask,
+ TCGv_i64 set_mask, uint32_t store_mask)
{
- TCGv_i64 t0;
+ TCGv_i64 fpscr_masked = tcg_temp_new_i64();
+ TCGv_i32 st_mask = tcg_constant_i32(store_mask);
- if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
- return gen_mffs(ctx);
- }
+ tcg_gen_andi_i64(fpscr_masked, fpscr, ~clear_mask);
+ tcg_gen_or_i64(fpscr_masked, fpscr_masked, set_mask);
+ gen_helper_store_fpscr(tcg_env, fpscr_masked, st_mask);
+}
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
+static bool trans_MFFS_ISA207(DisasContext *ctx, arg_X_t_rc *a)
+{
+ if (!(ctx->insns_flags2 & PPC2_ISA300)) {
+ /*
+ * Before Power ISA v3.0, MFFS bits 11~15 were reserved, any instruction
+ * with OPCD=63 and XO=583 should be decoded as MFFS.
+ */
+ return trans_MFFS(ctx, a);
}
- t0 = tcg_temp_new_i64();
- gen_reset_fpstatus();
- tcg_gen_extu_tl_i64(t0, cpu_fpscr);
- /* Mask everything except mode, status, and enables. */
- tcg_gen_andi_i64(t0, t0, FP_DRN | FP_STATUS | FP_ENABLES | FP_RN);
- set_fpr(rD(ctx->opcode), t0);
- tcg_temp_free_i64(t0);
+ /*
+ * For Power ISA v3.0+, return false and let the pattern group
+ * select the correct instruction.
+ */
+ return false;
}
-/* mffsce */
-static void gen_mffsce(DisasContext *ctx)
+static bool trans_MFFS(DisasContext *ctx, arg_X_t_rc *a)
{
- TCGv_i64 t0;
- TCGv_i32 mask;
+ REQUIRE_FPU(ctx);
- if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
- return gen_mffs(ctx);
+ gen_reset_fpstatus();
+ place_from_fpscr(a->rt, UINT64_MAX);
+ if (a->rc) {
+ gen_set_cr1_from_fpscr(ctx);
}
+ return true;
+}
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
+static bool trans_MFFSCE(DisasContext *ctx, arg_X_t *a)
+{
+ TCGv_i64 fpscr;
- t0 = tcg_temp_new_i64();
+ REQUIRE_FPU(ctx);
gen_reset_fpstatus();
- tcg_gen_extu_tl_i64(t0, cpu_fpscr);
- set_fpr(rD(ctx->opcode), t0);
-
- /* Clear exception enable bits in the FPSCR. */
- tcg_gen_andi_i64(t0, t0, ~FP_ENABLES);
- mask = tcg_const_i32(0x0003);
- gen_helper_store_fpscr(cpu_env, t0, mask);
-
- tcg_temp_free_i32(mask);
- tcg_temp_free_i64(t0);
+ fpscr = place_from_fpscr(a->rt, UINT64_MAX);
+ store_fpscr_masked(fpscr, FP_ENABLES, tcg_constant_i64(0), 0x0003);
+ return true;
}
-static void gen_helper_mffscrn(DisasContext *ctx, TCGv_i64 t1)
+static bool trans_MFFSCRN(DisasContext *ctx, arg_X_tb *a)
{
- TCGv_i64 t0 = tcg_temp_new_i64();
- TCGv_i32 mask = tcg_const_i32(0x0001);
+ TCGv_i64 t1, fpscr;
+
+ REQUIRE_FPU(ctx);
+
+ t1 = tcg_temp_new_i64();
+ get_fpr(t1, a->rb);
+ tcg_gen_andi_i64(t1, t1, FP_RN);
gen_reset_fpstatus();
- tcg_gen_extu_tl_i64(t0, cpu_fpscr);
- tcg_gen_andi_i64(t0, t0, FP_DRN | FP_ENABLES | FP_RN);
- set_fpr(rD(ctx->opcode), t0);
+ fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+ store_fpscr_masked(fpscr, FP_RN, t1, 0x0001);
+ return true;
+}
- /* Mask FPSCR value to clear RN. */
- tcg_gen_andi_i64(t0, t0, ~FP_RN);
+static bool trans_MFFSCDRN(DisasContext *ctx, arg_X_tb *a)
+{
+ TCGv_i64 t1, fpscr;
- /* Merge RN into FPSCR value. */
- tcg_gen_or_i64(t0, t0, t1);
+ REQUIRE_FPU(ctx);
- gen_helper_store_fpscr(cpu_env, t0, mask);
+ t1 = tcg_temp_new_i64();
+ get_fpr(t1, a->rb);
+ tcg_gen_andi_i64(t1, t1, FP_DRN);
- tcg_temp_free_i32(mask);
- tcg_temp_free_i64(t0);
+ gen_reset_fpstatus();
+ fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+ store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
+ return true;
}
-/* mffscrn */
-static void gen_mffscrn(DisasContext *ctx)
+static bool trans_MFFSCRNI(DisasContext *ctx, arg_X_imm2 *a)
{
- TCGv_i64 t1;
+ TCGv_i64 t1, fpscr;
- if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
- return gen_mffs(ctx);
- }
-
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
+ REQUIRE_FPU(ctx);
t1 = tcg_temp_new_i64();
- get_fpr(t1, rB(ctx->opcode));
- /* Mask FRB to get just RN. */
- tcg_gen_andi_i64(t1, t1, FP_RN);
-
- gen_helper_mffscrn(ctx, t1);
+ tcg_gen_movi_i64(t1, a->imm);
- tcg_temp_free_i64(t1);
+ gen_reset_fpstatus();
+ fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+ store_fpscr_masked(fpscr, FP_RN, t1, 0x0001);
+ return true;
}
-/* mffscrni */
-static void gen_mffscrni(DisasContext *ctx)
+static bool trans_MFFSCDRNI(DisasContext *ctx, arg_X_imm3 *a)
{
- TCGv_i64 t1;
+ TCGv_i64 t1, fpscr;
- if (unlikely(!(ctx->insns_flags2 & PPC2_ISA300))) {
- return gen_mffs(ctx);
- }
+ REQUIRE_FPU(ctx);
- if (unlikely(!ctx->fpu_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_FPU);
- return;
- }
+ t1 = tcg_temp_new_i64();
+ tcg_gen_movi_i64(t1, (uint64_t)a->imm << FPSCR_DRN0);
- t1 = tcg_const_i64((uint64_t)RM(ctx->opcode));
+ gen_reset_fpstatus();
+ fpscr = place_from_fpscr(a->rt, FP_DRN | FP_ENABLES | FP_NI | FP_RN);
+ store_fpscr_masked(fpscr, FP_DRN, t1, 0x0100);
+ return true;
+}
- gen_helper_mffscrn(ctx, t1);
+static bool trans_MFFSL(DisasContext *ctx, arg_X_t *a)
+{
+ REQUIRE_FPU(ctx);
- tcg_temp_free_i64(t1);
+ gen_reset_fpstatus();
+ place_from_fpscr(a->rt, FP_DRN | FP_STATUS | FP_ENABLES | FP_NI | FP_RN);
+ return true;
}
/* mtfsb0 */
@@ -748,10 +691,7 @@ static void gen_mtfsb0(DisasContext *ctx)
crb = 31 - crbD(ctx->opcode);
gen_reset_fpstatus();
if (likely(crb != FPSCR_FEX && crb != FPSCR_VX)) {
- TCGv_i32 t0;
- t0 = tcg_const_i32(crb);
- gen_helper_fpscr_clrbit(cpu_env, t0);
- tcg_temp_free_i32(t0);
+ gen_helper_fpscr_clrbit(tcg_env, tcg_constant_i32(crb));
}
if (unlikely(Rc(ctx->opcode) != 0)) {
tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
@@ -769,20 +709,16 @@ static void gen_mtfsb1(DisasContext *ctx)
return;
}
crb = 31 - crbD(ctx->opcode);
- gen_reset_fpstatus();
/* XXX: we pretend we can only do IEEE floating-point computations */
if (likely(crb != FPSCR_FEX && crb != FPSCR_VX && crb != FPSCR_NI)) {
- TCGv_i32 t0;
- t0 = tcg_const_i32(crb);
- gen_helper_fpscr_setbit(cpu_env, t0);
- tcg_temp_free_i32(t0);
+ gen_helper_fpscr_setbit(tcg_env, tcg_constant_i32(crb));
}
if (unlikely(Rc(ctx->opcode) != 0)) {
tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a deferred exception */
- gen_helper_float_check_status(cpu_env);
+ gen_helper_fpscr_check_status(tcg_env);
}
/* mtfsf */
@@ -803,23 +739,22 @@ static void gen_mtfsf(DisasContext *ctx)
gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL);
return;
}
- gen_reset_fpstatus();
- if (l) {
- t0 = tcg_const_i32((ctx->insns_flags2 & PPC2_ISA205) ? 0xffff : 0xff);
+ if (!l) {
+ t0 = tcg_constant_i32(flm << (w * 8));
+ } else if (ctx->insns_flags2 & PPC2_ISA205) {
+ t0 = tcg_constant_i32(0xffff);
} else {
- t0 = tcg_const_i32(flm << (w * 8));
+ t0 = tcg_constant_i32(0xff);
}
t1 = tcg_temp_new_i64();
get_fpr(t1, rB(ctx->opcode));
- gen_helper_store_fpscr(cpu_env, t1, t0);
- tcg_temp_free_i32(t0);
+ gen_helper_store_fpscr(tcg_env, t1, t0);
if (unlikely(Rc(ctx->opcode) != 0)) {
tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a deferred exception */
- gen_helper_float_check_status(cpu_env);
- tcg_temp_free_i64(t1);
+ gen_helper_fpscr_check_status(tcg_env);
}
/* mtfsfi */
@@ -840,132 +775,30 @@ static void gen_mtfsfi(DisasContext *ctx)
return;
}
sh = (8 * w) + 7 - bf;
- gen_reset_fpstatus();
- t0 = tcg_const_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
- t1 = tcg_const_i32(1 << sh);
- gen_helper_store_fpscr(cpu_env, t0, t1);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i32(t1);
+ t0 = tcg_constant_i64(((uint64_t)FPIMM(ctx->opcode)) << (4 * sh));
+ t1 = tcg_constant_i32(1 << sh);
+ gen_helper_store_fpscr(tcg_env, t0, t1);
if (unlikely(Rc(ctx->opcode) != 0)) {
tcg_gen_trunc_tl_i32(cpu_crf[1], cpu_fpscr);
tcg_gen_shri_i32(cpu_crf[1], cpu_crf[1], FPSCR_OX);
}
/* We can raise a deferred exception */
- gen_helper_float_check_status(cpu_env);
-}
-
-/*** Floating-point load ***/
-#define GEN_LDF(name, ldop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##ldop(ctx, t0, EA); \
- set_fpr(rD(ctx->opcode), t0); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
-}
-
-#define GEN_LDUF(name, ldop, opc, type) \
-static void glue(gen_, name##u)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- if (unlikely(rA(ctx->opcode) == 0)) { \
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_imm_index(ctx, EA, 0); \
- gen_qemu_##ldop(ctx, t0, EA); \
- set_fpr(rD(ctx->opcode), t0); \
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
-}
-
-#define GEN_LDUXF(name, ldop, opc, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- t0 = tcg_temp_new_i64(); \
- if (unlikely(rA(ctx->opcode) == 0)) { \
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- gen_addr_reg_index(ctx, EA); \
- gen_qemu_##ldop(ctx, t0, EA); \
- set_fpr(rD(ctx->opcode), t0); \
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
+ gen_helper_fpscr_check_status(tcg_env);
}
-#define GEN_LDXF(name, ldop, opc2, opc3, type) \
-static void glue(gen_, name##x)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_reg_index(ctx, EA); \
- gen_qemu_##ldop(ctx, t0, EA); \
- set_fpr(rD(ctx->opcode), t0); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
-}
-
-#define GEN_LDFS(name, ldop, op, type) \
-GEN_LDF(name, ldop, op | 0x20, type); \
-GEN_LDUF(name, ldop, op | 0x21, type); \
-GEN_LDUXF(name, ldop, op | 0x01, type); \
-GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
-
static void gen_qemu_ld32fs(DisasContext *ctx, TCGv_i64 dest, TCGv addr)
{
TCGv_i32 tmp = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
gen_helper_todouble(dest, tmp);
- tcg_temp_free_i32(tmp);
}
- /* lfd lfdu lfdux lfdx */
-GEN_LDFS(lfd, ld64_i64, 0x12, PPC_FLOAT);
- /* lfs lfsu lfsux lfsx */
-GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT);
-
/* lfdepx (external PID lfdx) */
static void gen_lfdepx(DisasContext *ctx)
{
TCGv EA;
TCGv_i64 t0;
- CHK_SV;
+ CHK_SV(ctx);
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
@@ -974,10 +807,8 @@ static void gen_lfdepx(DisasContext *ctx)
EA = tcg_temp_new();
t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_Q));
+ tcg_gen_qemu_ld_i64(t0, EA, PPC_TLB_EPID_LOAD, DEF_MEMOP(MO_UQ));
set_fpr(rD(ctx->opcode), t0);
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
/* lfdp */
@@ -1010,8 +841,6 @@ static void gen_lfdp(DisasContext *ctx)
gen_qemu_ld64_i64(ctx, t0, EA);
set_fpr(rD(ctx->opcode) + 1, t0);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
/* lfdpx */
@@ -1044,8 +873,6 @@ static void gen_lfdpx(DisasContext *ctx)
gen_qemu_ld64_i64(ctx, t0, EA);
set_fpr(rD(ctx->opcode) + 1, t0);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
/* lfiwax */
@@ -1066,9 +893,6 @@ static void gen_lfiwax(DisasContext *ctx)
gen_qemu_ld32s(ctx, t0, EA);
tcg_gen_ext_tl_i64(t1, t0);
set_fpr(rD(ctx->opcode), t1);
- tcg_temp_free(EA);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
}
/* lfiwzx */
@@ -1086,75 +910,6 @@ static void gen_lfiwzx(DisasContext *ctx)
gen_addr_reg_index(ctx, EA);
gen_qemu_ld32u_i64(ctx, t0, EA);
set_fpr(rD(ctx->opcode), t0);
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
-}
-/*** Floating-point store ***/
-#define GEN_STF(name, stop, opc, type) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_imm_index(ctx, EA, 0); \
- get_fpr(t0, rS(ctx->opcode)); \
- gen_qemu_##stop(ctx, t0, EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
-}
-
-#define GEN_STUF(name, stop, opc, type) \
-static void glue(gen_, name##u)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- if (unlikely(rA(ctx->opcode) == 0)) { \
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_imm_index(ctx, EA, 0); \
- get_fpr(t0, rS(ctx->opcode)); \
- gen_qemu_##stop(ctx, t0, EA); \
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
-}
-
-#define GEN_STUXF(name, stop, opc, type) \
-static void glue(gen_, name##ux)(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 t0; \
- if (unlikely(!ctx->fpu_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_FPU); \
- return; \
- } \
- if (unlikely(rA(ctx->opcode) == 0)) { \
- gen_inval_exception(ctx, POWERPC_EXCP_INVAL_INVAL); \
- return; \
- } \
- gen_set_access_type(ctx, ACCESS_FLOAT); \
- EA = tcg_temp_new(); \
- t0 = tcg_temp_new_i64(); \
- gen_addr_reg_index(ctx, EA); \
- get_fpr(t0, rS(ctx->opcode)); \
- gen_qemu_##stop(ctx, t0, EA); \
- tcg_gen_mov_tl(cpu_gpr[rA(ctx->opcode)], EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
}
#define GEN_STXF(name, stop, opc2, opc3, type) \
@@ -1172,35 +927,21 @@ static void glue(gen_, name##x)(DisasContext *ctx) \
gen_addr_reg_index(ctx, EA); \
get_fpr(t0, rS(ctx->opcode)); \
gen_qemu_##stop(ctx, t0, EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
}
-#define GEN_STFS(name, stop, op, type) \
-GEN_STF(name, stop, op | 0x20, type); \
-GEN_STUF(name, stop, op | 0x21, type); \
-GEN_STUXF(name, stop, op | 0x01, type); \
-GEN_STXF(name, stop, 0x17, op | 0x00, type)
-
static void gen_qemu_st32fs(DisasContext *ctx, TCGv_i64 src, TCGv addr)
{
TCGv_i32 tmp = tcg_temp_new_i32();
gen_helper_tosingle(tmp, src);
tcg_gen_qemu_st_i32(tmp, addr, ctx->mem_idx, DEF_MEMOP(MO_UL));
- tcg_temp_free_i32(tmp);
}
-/* stfd stfdu stfdux stfdx */
-GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT);
-/* stfs stfsu stfsux stfsx */
-GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT);
-
/* stfdepx (external PID lfdx) */
static void gen_stfdepx(DisasContext *ctx)
{
TCGv EA;
TCGv_i64 t0;
- CHK_SV;
+ CHK_SV(ctx);
if (unlikely(!ctx->fpu_enabled)) {
gen_exception(ctx, POWERPC_EXCP_FPU);
return;
@@ -1210,9 +951,7 @@ static void gen_stfdepx(DisasContext *ctx)
t0 = tcg_temp_new_i64();
gen_addr_reg_index(ctx, EA);
get_fpr(t0, rD(ctx->opcode));
- tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_Q));
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
+ tcg_gen_qemu_st_i64(t0, EA, PPC_TLB_EPID_STORE, DEF_MEMOP(MO_UQ));
}
/* stfdp */
@@ -1245,8 +984,6 @@ static void gen_stfdp(DisasContext *ctx)
get_fpr(t0, rD(ctx->opcode) + 1);
gen_qemu_st64_i64(ctx, t0, EA);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
/* stfdpx */
@@ -1279,8 +1016,6 @@ static void gen_stfdpx(DisasContext *ctx)
get_fpr(t0, rD(ctx->opcode) + 1);
gen_qemu_st64_i64(ctx, t0, EA);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
/* Optional: */
@@ -1289,189 +1024,92 @@ static inline void gen_qemu_st32fiw(DisasContext *ctx, TCGv_i64 arg1, TCGv arg2)
TCGv t0 = tcg_temp_new();
tcg_gen_trunc_i64_tl(t0, arg1),
gen_qemu_st32(ctx, t0, arg2);
- tcg_temp_free(t0);
}
/* stfiwx */
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX);
-/* POWER2 specific instructions */
-/* Quad manipulation (load/store two floats at a time) */
-
-/* lfq */
-static void gen_lfq(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr(rd, t1);
- gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr((rd + 1) % 32, t1);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
-
-/* lfqu */
-static void gen_lfqu(DisasContext *ctx)
+/* Floating-point Load/Store Instructions */
+static bool do_lsfpsd(DisasContext *ctx, int rt, int ra, TCGv displ,
+ bool update, bool store, bool single)
{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new();
- t2 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- gen_qemu_ld64_i64(ctx, t2, t0);
- set_fpr(rd, t2);
- gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, t2, t1);
- set_fpr((rd + 1) % 32, t2);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ TCGv ea;
+ TCGv_i64 t0;
+ REQUIRE_INSNS_FLAGS(ctx, FLOAT);
+ REQUIRE_FPU(ctx);
+ if (update && ra == 0) {
+ gen_invalid(ctx);
+ return true;
}
- tcg_temp_free(t0);
- tcg_temp_free(t1);
- tcg_temp_free_i64(t2);
-}
-
-/* lfqux */
-static void gen_lfqux(DisasContext *ctx)
-{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
gen_set_access_type(ctx, ACCESS_FLOAT);
- TCGv t0, t1;
- TCGv_i64 t2;
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, t2, t0);
- set_fpr(rd, t2);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- gen_qemu_ld64_i64(ctx, t2, t1);
- set_fpr((rd + 1) % 32, t2);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ t0 = tcg_temp_new_i64();
+ ea = do_ea_calc(ctx, ra, displ);
+ if (store) {
+ get_fpr(t0, rt);
+ if (single) {
+ gen_qemu_st32fs(ctx, t0, ea);
+ } else {
+ gen_qemu_st64_i64(ctx, t0, ea);
+ }
+ } else {
+ if (single) {
+ gen_qemu_ld32fs(ctx, t0, ea);
+ } else {
+ gen_qemu_ld64_i64(ctx, t0, ea);
+ }
+ set_fpr(rt, t0);
}
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
-}
-
-/* lfqx */
-static void gen_lfqx(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_reg_index(ctx, t0);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr(rd, t1);
- gen_addr_add(ctx, t0, t0, 8);
- gen_qemu_ld64_i64(ctx, t1, t0);
- set_fpr((rd + 1) % 32, t1);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
+ if (update) {
+ tcg_gen_mov_tl(cpu_gpr[ra], ea);
+ }
+ return true;
}
-/* stfq */
-static void gen_stfq(DisasContext *ctx)
+static bool do_lsfp_D(DisasContext *ctx, arg_D *a, bool update, bool store,
+ bool single)
{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t0 = tcg_temp_new();
- t1 = tcg_temp_new_i64();
- gen_addr_imm_index(ctx, t0, 0);
- get_fpr(t1, rd);
- gen_qemu_st64_i64(ctx, t1, t0);
- gen_addr_add(ctx, t0, t0, 8);
- get_fpr(t1, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t1, t0);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
+ return do_lsfpsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), update, store,
+ single);
}
-/* stfqu */
-static void gen_stfqu(DisasContext *ctx)
+static bool do_lsfp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool update,
+ bool store, bool single)
{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_imm_index(ctx, t0, 0);
- get_fpr(t2, rd);
- gen_qemu_st64_i64(ctx, t2, t0);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- get_fpr(t2, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t2, t1);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
+ arg_D d;
+ if (!resolve_PLS_D(ctx, &d, a)) {
+ return true;
}
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
+ return do_lsfp_D(ctx, &d, update, store, single);
}
-/* stfqux */
-static void gen_stfqux(DisasContext *ctx)
+static bool do_lsfp_X(DisasContext *ctx, arg_X *a, bool update,
+ bool store, bool single)
{
- int ra = rA(ctx->opcode);
- int rd = rD(ctx->opcode);
- TCGv t0, t1;
- TCGv_i64 t2;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t2 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- get_fpr(t2, rd);
- gen_qemu_st64_i64(ctx, t2, t0);
- t1 = tcg_temp_new();
- gen_addr_add(ctx, t1, t0, 8);
- get_fpr(t2, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t2, t1);
- tcg_temp_free(t1);
- if (ra != 0) {
- tcg_gen_mov_tl(cpu_gpr[ra], t0);
- }
- tcg_temp_free(t0);
- tcg_temp_free_i64(t2);
+ return do_lsfpsd(ctx, a->rt, a->ra, cpu_gpr[a->rb], update, store, single);
}
-/* stfqx */
-static void gen_stfqx(DisasContext *ctx)
-{
- int rd = rD(ctx->opcode);
- TCGv t0;
- TCGv_i64 t1;
- gen_set_access_type(ctx, ACCESS_FLOAT);
- t1 = tcg_temp_new_i64();
- t0 = tcg_temp_new();
- gen_addr_reg_index(ctx, t0);
- get_fpr(t1, rd);
- gen_qemu_st64_i64(ctx, t1, t0);
- gen_addr_add(ctx, t0, t0, 8);
- get_fpr(t1, (rd + 1) % 32);
- gen_qemu_st64_i64(ctx, t1, t0);
- tcg_temp_free(t0);
- tcg_temp_free_i64(t1);
-}
+TRANS(LFS, do_lsfp_D, false, false, true)
+TRANS(LFSU, do_lsfp_D, true, false, true)
+TRANS(LFSX, do_lsfp_X, false, false, true)
+TRANS(LFSUX, do_lsfp_X, true, false, true)
+TRANS(PLFS, do_lsfp_PLS_D, false, false, true)
+
+TRANS(LFD, do_lsfp_D, false, false, false)
+TRANS(LFDU, do_lsfp_D, true, false, false)
+TRANS(LFDX, do_lsfp_X, false, false, false)
+TRANS(LFDUX, do_lsfp_X, true, false, false)
+TRANS(PLFD, do_lsfp_PLS_D, false, false, false)
+
+TRANS(STFS, do_lsfp_D, false, true, true)
+TRANS(STFSU, do_lsfp_D, true, true, true)
+TRANS(STFSX, do_lsfp_X, false, true, true)
+TRANS(STFSUX, do_lsfp_X, true, true, true)
+TRANS(PSTFS, do_lsfp_PLS_D, false, true, true)
+
+TRANS(STFD, do_lsfp_D, false, true, false)
+TRANS(STFDU, do_lsfp_D, true, true, false)
+TRANS(STFDX, do_lsfp_X, false, true, false)
+TRANS(STFDUX, do_lsfp_X, true, true, false)
+TRANS(PSTFD, do_lsfp_PLS_D, false, true, false)
#undef _GEN_FLOAT_ACB
#undef GEN_FLOAT_ACB
diff --git a/target/ppc/translate/fp-ops.c.inc b/target/ppc/translate/fp-ops.c.inc
index 88fab65628..d4c6c4bed1 100644
--- a/target/ppc/translate/fp-ops.c.inc
+++ b/target/ppc/translate/fp-ops.c.inc
@@ -24,7 +24,6 @@ GEN_FLOAT_AC(mul, 0x19, 0x0000F800, 1, PPC_FLOAT),
GEN_FLOAT_BS(re, 0x3F, 0x18, 1, PPC_FLOAT_EXT),
GEN_FLOAT_BS(res, 0x3B, 0x18, 1, PPC_FLOAT_FRES),
GEN_FLOAT_BS(rsqrte, 0x3F, 0x1A, 1, PPC_FLOAT_FRSQRTE),
-_GEN_FLOAT_ACB(sel, sel, 0x3F, 0x17, 0, 0, PPC_FLOAT_FSEL),
GEN_FLOAT_AB(sub, 0x14, 0x000007C0, 1, PPC_FLOAT),
GEN_FLOAT_ACB(madd, 0x1D, 1, PPC_FLOAT),
GEN_FLOAT_ACB(msub, 0x1C, 1, PPC_FLOAT),
@@ -50,50 +49,19 @@ GEN_FLOAT_B(riz, 0x08, 0x0D, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(rip, 0x08, 0x0E, 1, PPC_FLOAT_EXT),
GEN_FLOAT_B(rim, 0x08, 0x0F, 1, PPC_FLOAT_EXT),
-#define GEN_LDF(name, ldop, opc, type) \
-GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
-#define GEN_LDUF(name, ldop, opc, type) \
-GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
-#define GEN_LDUXF(name, ldop, opc, type) \
-GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
-#define GEN_LDXF(name, ldop, opc2, opc3, type) \
-GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_LDFS(name, ldop, op, type) \
-GEN_LDF(name, ldop, op | 0x20, type) \
-GEN_LDUF(name, ldop, op | 0x21, type) \
-GEN_LDUXF(name, ldop, op | 0x01, type) \
-GEN_LDXF(name, ldop, 0x17, op | 0x00, type)
-
-GEN_LDFS(lfd, ld64, 0x12, PPC_FLOAT)
-GEN_LDFS(lfs, ld32fs, 0x10, PPC_FLOAT)
GEN_HANDLER_E(lfdepx, 0x1F, 0x1F, 0x12, 0x00000001, PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER_E(lfiwax, 0x1f, 0x17, 0x1a, 0x00000001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(lfiwzx, 0x1f, 0x17, 0x1b, 0x1, PPC_NONE, PPC2_FP_CVT_ISA206),
GEN_HANDLER_E(lfdpx, 0x1F, 0x17, 0x18, 0x00200001, PPC_NONE, PPC2_ISA205),
-#define GEN_STF(name, stop, opc, type) \
-GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
-#define GEN_STUF(name, stop, opc, type) \
-GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
-#define GEN_STUXF(name, stop, opc, type) \
-GEN_HANDLER(name##ux, 0x1F, 0x17, opc, 0x00000001, type),
#define GEN_STXF(name, stop, opc2, opc3, type) \
GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_STFS(name, stop, op, type) \
-GEN_STF(name, stop, op | 0x20, type) \
-GEN_STUF(name, stop, op | 0x21, type) \
-GEN_STUXF(name, stop, op | 0x01, type) \
-GEN_STXF(name, stop, 0x17, op | 0x00, type)
-GEN_STFS(stfd, st64_i64, 0x16, PPC_FLOAT)
-GEN_STFS(stfs, st32fs, 0x14, PPC_FLOAT)
GEN_STXF(stfiw, st32fiw, 0x17, 0x1E, PPC_FLOAT_STFIWX)
GEN_HANDLER_E(stfdepx, 0x1F, 0x1F, 0x16, 0x00000001, PPC_NONE, PPC2_BOOKE206),
GEN_HANDLER_E(stfdpx, 0x1F, 0x17, 0x1C, 0x00200001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER(frsqrtes, 0x3B, 0x1A, 0xFF, 0x001F07C0, PPC_FLOAT_FRSQRTES),
-GEN_HANDLER(fsqrt, 0x3F, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
-GEN_HANDLER(fsqrts, 0x3B, 0x16, 0xFF, 0x001F07C0, PPC_FLOAT_FSQRT),
GEN_HANDLER(fcmpo, 0x3F, 0x00, 0x01, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fcmpu, 0x3F, 0x00, 0x00, 0x00600001, PPC_FLOAT),
GEN_HANDLER(fabs, 0x3F, 0x08, 0x08, 0x001F0000, PPC_FLOAT),
@@ -104,15 +72,6 @@ GEN_HANDLER_E(fcpsgn, 0x3F, 0x08, 0x00, 0x00000000, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(fmrgew, 0x3F, 0x06, 0x1E, 0x00000001, PPC_NONE, PPC2_VSX207),
GEN_HANDLER_E(fmrgow, 0x3F, 0x06, 0x1A, 0x00000001, PPC_NONE, PPC2_VSX207),
GEN_HANDLER(mcrfs, 0x3F, 0x00, 0x02, 0x0063F801, PPC_FLOAT),
-GEN_HANDLER_E_2(mffs, 0x3F, 0x07, 0x12, 0x00, 0x00000000, PPC_FLOAT, PPC_NONE),
-GEN_HANDLER_E_2(mffsce, 0x3F, 0x07, 0x12, 0x01, 0x00000000, PPC_FLOAT,
- PPC2_ISA300),
-GEN_HANDLER_E_2(mffsl, 0x3F, 0x07, 0x12, 0x18, 0x00000000, PPC_FLOAT,
- PPC2_ISA300),
-GEN_HANDLER_E_2(mffscrn, 0x3F, 0x07, 0x12, 0x16, 0x00000000, PPC_FLOAT,
- PPC_NONE),
-GEN_HANDLER_E_2(mffscrni, 0x3F, 0x07, 0x12, 0x17, 0x00000000, PPC_FLOAT,
- PPC_NONE),
GEN_HANDLER(mtfsb0, 0x3F, 0x06, 0x02, 0x001FF800, PPC_FLOAT),
GEN_HANDLER(mtfsb1, 0x3F, 0x06, 0x01, 0x001FF800, PPC_FLOAT),
GEN_HANDLER(mtfsf, 0x3F, 0x07, 0x16, 0x00000000, PPC_FLOAT),
diff --git a/target/ppc/translate/processor-ctrl-impl.c.inc b/target/ppc/translate/processor-ctrl-impl.c.inc
new file mode 100644
index 0000000000..0142801985
--- /dev/null
+++ b/target/ppc/translate/processor-ctrl-impl.c.inc
@@ -0,0 +1,105 @@
+/*
+ * Power ISA decode for Storage Control instructions
+ *
+ * Copyright (c) 2022 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Processor Control Instructions
+ */
+
+static bool trans_MSGCLR(DisasContext *ctx, arg_X_rb *a)
+{
+ if (!(ctx->insns_flags2 & PPC2_ISA207S)) {
+ /*
+ * Before Power ISA 2.07, processor control instructions were only
+ * implemented in the "Embedded.Processor Control" category.
+ */
+ REQUIRE_INSNS_FLAGS2(ctx, PRCNTL);
+ }
+
+ REQUIRE_HV(ctx);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (is_book3s_arch2x(ctx)) {
+ gen_helper_book3s_msgclr(tcg_env, cpu_gpr[a->rb]);
+ } else {
+ gen_helper_msgclr(tcg_env, cpu_gpr[a->rb]);
+ }
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_MSGSND(DisasContext *ctx, arg_X_rb *a)
+{
+ if (!(ctx->insns_flags2 & PPC2_ISA207S)) {
+ /*
+ * Before Power ISA 2.07, processor control instructions were only
+ * implemented in the "Embedded.Processor Control" category.
+ */
+ REQUIRE_INSNS_FLAGS2(ctx, PRCNTL);
+ }
+
+ REQUIRE_HV(ctx);
+
+#if !defined(CONFIG_USER_ONLY)
+ if (is_book3s_arch2x(ctx)) {
+ gen_helper_book3s_msgsnd(cpu_gpr[a->rb]);
+ } else {
+ gen_helper_msgsnd(cpu_gpr[a->rb]);
+ }
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_MSGCLRP(DisasContext *ctx, arg_X_rb *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA207S);
+ REQUIRE_SV(ctx);
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_book3s_msgclrp(tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_MSGSNDP(DisasContext *ctx, arg_X_rb *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA207S);
+ REQUIRE_SV(ctx);
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_book3s_msgsndp(tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_MSGSYNC(DisasContext *ctx, arg_MSGSYNC *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_HV(ctx);
+
+ /* interpreted as no-op */
+ return true;
+}
diff --git a/target/ppc/translate/spe-impl.c.inc b/target/ppc/translate/spe-impl.c.inc
index 2e6e799a25..454dac823e 100644
--- a/target/ppc/translate/spe-impl.c.inc
+++ b/target/ppc/translate/spe-impl.c.inc
@@ -22,8 +22,7 @@ static inline void gen_evmra(DisasContext *ctx)
cpu_gprh[rA(ctx->opcode)]);
/* spe_acc := tmp */
- tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
- tcg_temp_free_i64(tmp);
+ tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc));
/* rD := rA */
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
@@ -96,8 +95,6 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
tcg_opi(t0, t0, rB(ctx->opcode)); \
tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
- \
- tcg_temp_free_i32(t0); \
}
GEN_SPEOP_TCG_LOGIC_IMM2(evslwi, tcg_gen_shli_i32);
GEN_SPEOP_TCG_LOGIC_IMM2(evsrwiu, tcg_gen_shri_i32);
@@ -122,8 +119,6 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_gen_trunc_tl_i32(t0, cpu_gprh[rA(ctx->opcode)]); \
tcg_op(t0, t0); \
tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
- \
- tcg_temp_free_i32(t0); \
}
GEN_SPEOP_ARITH1(evabs, tcg_gen_abs_i32);
@@ -159,16 +154,13 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_gen_trunc_tl_i32(t1, cpu_gprh[rB(ctx->opcode)]); \
tcg_op(t0, t0, t1); \
tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
- \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
}
static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- TCGv_i32 t0 = tcg_temp_local_new_i32();
+ TCGv_i32 t0 = tcg_temp_new_i32();
/* No error here: 6 bits are used */
tcg_gen_andi_i32(t0, arg2, 0x3F);
@@ -178,14 +170,13 @@ static inline void gen_op_evsrwu(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
gen_set_label(l1);
tcg_gen_movi_i32(ret, 0);
gen_set_label(l2);
- tcg_temp_free_i32(t0);
}
GEN_SPEOP_ARITH2(evsrwu, gen_op_evsrwu);
static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- TCGv_i32 t0 = tcg_temp_local_new_i32();
+ TCGv_i32 t0 = tcg_temp_new_i32();
/* No error here: 6 bits are used */
tcg_gen_andi_i32(t0, arg2, 0x3F);
@@ -195,14 +186,13 @@ static inline void gen_op_evsrws(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
gen_set_label(l1);
tcg_gen_movi_i32(ret, 0);
gen_set_label(l2);
- tcg_temp_free_i32(t0);
}
GEN_SPEOP_ARITH2(evsrws, gen_op_evsrws);
static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
{
TCGLabel *l1 = gen_new_label();
TCGLabel *l2 = gen_new_label();
- TCGv_i32 t0 = tcg_temp_local_new_i32();
+ TCGv_i32 t0 = tcg_temp_new_i32();
/* No error here: 6 bits are used */
tcg_gen_andi_i32(t0, arg2, 0x3F);
@@ -212,7 +202,6 @@ static inline void gen_op_evslw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
gen_set_label(l1);
tcg_gen_movi_i32(ret, 0);
gen_set_label(l2);
- tcg_temp_free_i32(t0);
}
GEN_SPEOP_ARITH2(evslw, gen_op_evslw);
static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
@@ -220,7 +209,6 @@ static inline void gen_op_evrlw(TCGv_i32 ret, TCGv_i32 arg1, TCGv_i32 arg2)
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_andi_i32(t0, arg2, 0x1F);
tcg_gen_rotl_i32(ret, arg1, t0);
- tcg_temp_free_i32(t0);
}
GEN_SPEOP_ARITH2(evrlw, gen_op_evrlw);
static inline void gen_evmergehi(DisasContext *ctx)
@@ -257,8 +245,6 @@ static inline void gen_##name(DisasContext *ctx) \
tcg_gen_trunc_tl_i32(t0, cpu_gprh[rB(ctx->opcode)]); \
tcg_op(t0, t0, rA(ctx->opcode)); \
tcg_gen_extu_i32_tl(cpu_gprh[rD(ctx->opcode)], t0); \
- \
- tcg_temp_free_i32(t0); \
}
GEN_SPEOP_ARITH_IMM2(evaddiw, tcg_gen_addi_i32);
GEN_SPEOP_ARITH_IMM2(evsubifw, tcg_gen_subi_i32);
@@ -341,7 +327,6 @@ static inline void gen_evmergelohi(DisasContext *ctx)
tcg_gen_mov_tl(tmp, cpu_gpr[rA(ctx->opcode)]);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], tmp);
- tcg_temp_free(tmp);
} else {
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rB(ctx->opcode)]);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
@@ -378,7 +363,7 @@ static inline void gen_evsel(DisasContext *ctx)
TCGLabel *l2 = gen_new_label();
TCGLabel *l3 = gen_new_label();
TCGLabel *l4 = gen_new_label();
- TCGv_i32 t0 = tcg_temp_local_new_i32();
+ TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_andi_i32(t0, cpu_crf[ctx->opcode & 0x07], 1 << 3);
tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l1);
@@ -394,7 +379,6 @@ static inline void gen_evsel(DisasContext *ctx)
gen_set_label(l3);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rB(ctx->opcode)]);
gen_set_label(l4);
- tcg_temp_free_i32(t0);
}
static void gen_evsel0(DisasContext *ctx)
@@ -456,9 +440,6 @@ static inline void gen_evmwumi(DisasContext *ctx)
tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
static inline void gen_evmwumia(DisasContext *ctx)
@@ -476,8 +457,7 @@ static inline void gen_evmwumia(DisasContext *ctx)
/* acc := rD */
gen_load_gpr64(tmp, rD(ctx->opcode));
- tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
- tcg_temp_free_i64(tmp);
+ tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc));
}
static inline void gen_evmwumiaa(DisasContext *ctx)
@@ -499,19 +479,16 @@ static inline void gen_evmwumiaa(DisasContext *ctx)
gen_load_gpr64(tmp, rD(ctx->opcode));
/* Load acc */
- tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
+ tcg_gen_ld_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc));
/* acc := tmp + acc */
tcg_gen_add_i64(acc, acc, tmp);
/* Store acc */
- tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
+ tcg_gen_st_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc));
/* rD := acc */
gen_store_gpr64(rD(ctx->opcode), acc);
-
- tcg_temp_free_i64(acc);
- tcg_temp_free_i64(tmp);
}
static inline void gen_evmwsmi(DisasContext *ctx)
@@ -535,9 +512,6 @@ static inline void gen_evmwsmi(DisasContext *ctx)
tcg_gen_mul_i64(t0, t0, t1); /* t0 := rA * rB */
gen_store_gpr64(rD(ctx->opcode), t0); /* rD := t0 */
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
}
static inline void gen_evmwsmia(DisasContext *ctx)
@@ -555,9 +529,7 @@ static inline void gen_evmwsmia(DisasContext *ctx)
/* acc := rD */
gen_load_gpr64(tmp, rD(ctx->opcode));
- tcg_gen_st_i64(tmp, cpu_env, offsetof(CPUPPCState, spe_acc));
-
- tcg_temp_free_i64(tmp);
+ tcg_gen_st_i64(tmp, tcg_env, offsetof(CPUPPCState, spe_acc));
}
static inline void gen_evmwsmiaa(DisasContext *ctx)
@@ -579,19 +551,16 @@ static inline void gen_evmwsmiaa(DisasContext *ctx)
gen_load_gpr64(tmp, rD(ctx->opcode));
/* Load acc */
- tcg_gen_ld_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
+ tcg_gen_ld_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc));
/* acc := tmp + acc */
tcg_gen_add_i64(acc, acc, tmp);
/* Store acc */
- tcg_gen_st_i64(acc, cpu_env, offsetof(CPUPPCState, spe_acc));
+ tcg_gen_st_i64(acc, tcg_env, offsetof(CPUPPCState, spe_acc));
/* rD := acc */
gen_store_gpr64(rD(ctx->opcode), acc);
-
- tcg_temp_free_i64(acc);
- tcg_temp_free_i64(tmp);
}
GEN_SPE(evaddw, speundef, 0x00, 0x08, 0x00000000, 0xFFFFFFFF, PPC_SPE); ////
@@ -644,7 +613,6 @@ static inline void gen_op_evldd(DisasContext *ctx, TCGv addr)
TCGv_i64 t0 = tcg_temp_new_i64();
gen_qemu_ld64_i64(ctx, t0, addr);
gen_store_gpr64(rD(ctx->opcode), t0);
- tcg_temp_free_i64(t0);
}
static inline void gen_op_evldw(DisasContext *ctx, TCGv addr)
@@ -668,7 +636,6 @@ static inline void gen_op_evldh(DisasContext *ctx, TCGv addr)
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
@@ -678,7 +645,6 @@ static inline void gen_op_evlhhesplat(DisasContext *ctx, TCGv addr)
tcg_gen_shli_tl(t0, t0, 16);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
@@ -687,7 +653,6 @@ static inline void gen_op_evlhhousplat(DisasContext *ctx, TCGv addr)
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
@@ -696,7 +661,6 @@ static inline void gen_op_evlhhossplat(DisasContext *ctx, TCGv addr)
gen_qemu_ld16s(ctx, t0, addr);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
@@ -707,7 +671,6 @@ static inline void gen_op_evlwhe(DisasContext *ctx, TCGv addr)
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
- tcg_temp_free(t0);
}
static inline void gen_op_evlwhou(DisasContext *ctx, TCGv addr)
@@ -730,7 +693,6 @@ static inline void gen_op_evlwwsplat(DisasContext *ctx, TCGv addr)
gen_qemu_ld32u(ctx, t0, addr);
tcg_gen_mov_tl(cpu_gprh[rD(ctx->opcode)], t0);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
@@ -743,7 +705,6 @@ static inline void gen_op_evlwhsplat(DisasContext *ctx, TCGv addr)
gen_qemu_ld16u(ctx, t0, addr);
tcg_gen_shli_tl(cpu_gpr[rD(ctx->opcode)], t0, 16);
tcg_gen_or_tl(cpu_gpr[rD(ctx->opcode)], cpu_gprh[rD(ctx->opcode)], t0);
- tcg_temp_free(t0);
}
static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
@@ -751,7 +712,6 @@ static inline void gen_op_evstdd(DisasContext *ctx, TCGv addr)
TCGv_i64 t0 = tcg_temp_new_i64();
gen_load_gpr64(t0, rS(ctx->opcode));
gen_qemu_st64_i64(ctx, t0, addr);
- tcg_temp_free_i64(t0);
}
static inline void gen_op_evstdw(DisasContext *ctx, TCGv addr)
@@ -771,7 +731,6 @@ static inline void gen_op_evstdh(DisasContext *ctx, TCGv addr)
gen_addr_add(ctx, addr, addr, 2);
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
gen_qemu_st16(ctx, t0, addr);
- tcg_temp_free(t0);
gen_addr_add(ctx, addr, addr, 2);
gen_qemu_st16(ctx, cpu_gpr[rS(ctx->opcode)], addr);
}
@@ -784,7 +743,6 @@ static inline void gen_op_evstwhe(DisasContext *ctx, TCGv addr)
gen_addr_add(ctx, addr, addr, 2);
tcg_gen_shri_tl(t0, cpu_gpr[rS(ctx->opcode)], 16);
gen_qemu_st16(ctx, t0, addr);
- tcg_temp_free(t0);
}
static inline void gen_op_evstwho(DisasContext *ctx, TCGv addr)
@@ -820,7 +778,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
gen_addr_reg_index(ctx, t0); \
} \
gen_op_##name(ctx, t0); \
- tcg_temp_free(t0); \
}
GEN_SPEOP_LDST(evldd, 0x00, 3);
@@ -921,9 +878,8 @@ static inline void gen_##name(DisasContext *ctx) \
{ \
TCGv_i32 t0 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(t0, cpu_env, t0); \
+ gen_helper_##name(t0, tcg_env, t0); \
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
- tcg_temp_free_i32(t0); \
}
#define GEN_SPEFPUOP_CONV_32_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -937,10 +893,8 @@ static inline void gen_##name(DisasContext *ctx) \
t0 = tcg_temp_new_i64(); \
t1 = tcg_temp_new_i32(); \
gen_load_gpr64(t0, rB(ctx->opcode)); \
- gen_helper_##name(t1, cpu_env, t0); \
+ gen_helper_##name(t1, tcg_env, t0); \
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t1); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_CONV_64_32(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -954,10 +908,8 @@ static inline void gen_##name(DisasContext *ctx) \
t0 = tcg_temp_new_i64(); \
t1 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(t0, cpu_env, t1); \
+ gen_helper_##name(t0, tcg_env, t1); \
gen_store_gpr64(rD(ctx->opcode), t0); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_CONV_64_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -969,9 +921,8 @@ static inline void gen_##name(DisasContext *ctx) \
} \
t0 = tcg_temp_new_i64(); \
gen_load_gpr64(t0, rB(ctx->opcode)); \
- gen_helper_##name(t0, cpu_env, t0); \
+ gen_helper_##name(t0, tcg_env, t0); \
gen_store_gpr64(rD(ctx->opcode), t0); \
- tcg_temp_free_i64(t0); \
}
#define GEN_SPEFPUOP_ARITH2_32_32(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -980,11 +931,8 @@ static inline void gen_##name(DisasContext *ctx) \
TCGv_i32 t1 = tcg_temp_new_i32(); \
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(t0, cpu_env, t0, t1); \
+ gen_helper_##name(t0, tcg_env, t0, t1); \
tcg_gen_extu_i32_tl(cpu_gpr[rD(ctx->opcode)], t0); \
- \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
}
#define GEN_SPEFPUOP_ARITH2_64_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -998,10 +946,8 @@ static inline void gen_##name(DisasContext *ctx) \
t1 = tcg_temp_new_i64(); \
gen_load_gpr64(t0, rA(ctx->opcode)); \
gen_load_gpr64(t1, rB(ctx->opcode)); \
- gen_helper_##name(t0, cpu_env, t0, t1); \
+ gen_helper_##name(t0, tcg_env, t0, t1); \
gen_store_gpr64(rD(ctx->opcode), t0); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
}
#define GEN_SPEFPUOP_COMP_32(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -1011,10 +957,7 @@ static inline void gen_##name(DisasContext *ctx) \
\
tcg_gen_trunc_tl_i32(t0, cpu_gpr[rA(ctx->opcode)]); \
tcg_gen_trunc_tl_i32(t1, cpu_gpr[rB(ctx->opcode)]); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
- \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i32(t1); \
+ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], tcg_env, t0, t1); \
}
#define GEN_SPEFPUOP_COMP_64(name) \
static inline void gen_##name(DisasContext *ctx) \
@@ -1028,9 +971,7 @@ static inline void gen_##name(DisasContext *ctx) \
t1 = tcg_temp_new_i64(); \
gen_load_gpr64(t0, rA(ctx->opcode)); \
gen_load_gpr64(t1, rB(ctx->opcode)); \
- gen_helper_##name(cpu_crf[crfD(ctx->opcode)], cpu_env, t0, t1); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
+ gen_helper_##name(cpu_crf[crfD(ctx->opcode)], tcg_env, t0, t1); \
}
/* Single precision floating-point vectors operations */
diff --git a/target/ppc/translate/storage-ctrl-impl.c.inc b/target/ppc/translate/storage-ctrl-impl.c.inc
new file mode 100644
index 0000000000..74c23a4191
--- /dev/null
+++ b/target/ppc/translate/storage-ctrl-impl.c.inc
@@ -0,0 +1,248 @@
+/*
+ * Power ISA decode for Storage Control instructions
+ *
+ * Copyright (c) 2022 Instituto de Pesquisas Eldorado (eldorado.org.br)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Store Control Instructions
+ */
+
+#include "mmu-book3s-v3.h"
+
+static bool trans_SLBIE(DisasContext *ctx, arg_SLBIE *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SLBI);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBIE(tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBIEG(DisasContext *ctx, arg_SLBIEG *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBIEG(tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBIA(DisasContext *ctx, arg_SLBIA *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SLBI);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBIA(tcg_env, tcg_constant_i32(a->ih));
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBIAG(DisasContext *ctx, arg_SLBIAG *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBIAG(tcg_env, cpu_gpr[a->rs], tcg_constant_i32(a->l));
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBMTE(DisasContext *ctx, arg_SLBMTE *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBMTE(tcg_env, cpu_gpr[a->rb], cpu_gpr[a->rt]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBMFEV(DisasContext *ctx, arg_SLBMFEV *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBMFEV(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBMFEE(DisasContext *ctx, arg_SLBMFEE *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_helper_SLBMFEE(cpu_gpr[a->rt], tcg_env, cpu_gpr[a->rb]);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool trans_SLBFEE(DisasContext *ctx, arg_SLBFEE *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS(ctx, SEGMENT_64B);
+
+#if defined(CONFIG_USER_ONLY)
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+#else
+
+#if defined(TARGET_PPC64)
+ TCGLabel *l1, *l2;
+
+ if (unlikely(ctx->pr)) {
+ gen_inval_exception(ctx, POWERPC_EXCP_PRIV_REG);
+ return true;
+ }
+ gen_helper_SLBFEE(cpu_gpr[a->rt], tcg_env,
+ cpu_gpr[a->rb]);
+ l1 = gen_new_label();
+ l2 = gen_new_label();
+ tcg_gen_trunc_tl_i32(cpu_crf[0], cpu_so);
+ tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_gpr[a->rt], -1, l1);
+ tcg_gen_ori_i32(cpu_crf[0], cpu_crf[0], CRF_EQ);
+ tcg_gen_br(l2);
+ gen_set_label(l1);
+ tcg_gen_movi_tl(cpu_gpr[a->rt], 0);
+ gen_set_label(l2);
+#else
+ qemu_build_not_reached();
+#endif
+#endif
+ return true;
+}
+
+static bool trans_SLBSYNC(DisasContext *ctx, arg_SLBSYNC *a)
+{
+ REQUIRE_64BIT(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_SV(ctx);
+
+#if !defined(CONFIG_USER_ONLY) && defined(TARGET_PPC64)
+ gen_check_tlb_flush(ctx, true);
+#else
+ qemu_build_not_reached();
+#endif
+ return true;
+}
+
+static bool do_tlbie(DisasContext *ctx, arg_X_tlbie *a, bool local)
+{
+#if defined(CONFIG_USER_ONLY)
+ gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return true;
+#else
+ TCGv_i32 t1;
+ int rb;
+
+ rb = a->rb;
+
+ if ((ctx->insns_flags2 & PPC2_ISA300) == 0) {
+ /*
+ * Before Power ISA 3.0, the corresponding bits of RIC, PRS, and R
+ * (and RS for tlbiel) were reserved fields and should be ignored.
+ */
+ a->ric = 0;
+ a->prs = false;
+ a->r = false;
+ if (local) {
+ a->rs = 0;
+ }
+ }
+
+ if (ctx->pr) {
+ /* tlbie[l] is privileged... */
+ gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return true;
+ } else if (!ctx->hv) {
+ if ((!a->prs && ctx->hr) || (!local && !ctx->gtse)) {
+ /*
+ * ... except when PRS=0 and HR=1, or when GTSE=0 for tlbie,
+ * making it hypervisor privileged.
+ */
+ gen_priv_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+ return true;
+ }
+ }
+
+ if (!local && NARROW_MODE(ctx)) {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_ext32u_tl(t0, cpu_gpr[rb]);
+ gen_helper_tlbie(tcg_env, t0);
+
+#if defined(TARGET_PPC64)
+ /*
+ * ISA 3.1B says that MSR SF must be 1 when this instruction is executed;
+ * otherwise the results are undefined.
+ */
+ } else if (a->r) {
+ gen_helper_tlbie_isa300(tcg_env, cpu_gpr[rb], cpu_gpr[a->rs],
+ tcg_constant_i32(a->ric << TLBIE_F_RIC_SHIFT |
+ a->prs << TLBIE_F_PRS_SHIFT |
+ a->r << TLBIE_F_R_SHIFT |
+ local << TLBIE_F_LOCAL_SHIFT));
+ return true;
+#endif
+
+ } else {
+ gen_helper_tlbie(tcg_env, cpu_gpr[rb]);
+ }
+
+ if (local) {
+ return true;
+ }
+
+ t1 = tcg_temp_new_i32();
+ tcg_gen_ld_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));
+ tcg_gen_ori_i32(t1, t1, TLB_NEED_GLOBAL_FLUSH);
+ tcg_gen_st_i32(t1, tcg_env, offsetof(CPUPPCState, tlb_need_flush));
+
+ return true;
+#endif
+}
+
+TRANS_FLAGS(MEM_TLBIE, TLBIE, do_tlbie, false)
+TRANS_FLAGS(MEM_TLBIE, TLBIEL, do_tlbie, true)
diff --git a/target/ppc/translate/vector-impl.c.inc b/target/ppc/translate/vector-impl.c.inc
deleted file mode 100644
index 117ce9b137..0000000000
--- a/target/ppc/translate/vector-impl.c.inc
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Power ISA decode for Vector Facility instructions
- *
- * Copyright (c) 2021 Instituto de Pesquisas Eldorado (eldorado.org.br)
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, see <http://www.gnu.org/licenses/>.
- */
-
-#define REQUIRE_ALTIVEC(CTX) \
- do { \
- if (unlikely(!(CTX)->altivec_enabled)) { \
- gen_exception((CTX), POWERPC_EXCP_VPU); \
- return true; \
- } \
- } while (0)
-
-static bool trans_VCFUGED(DisasContext *ctx, arg_VX *a)
-{
- TCGv_i64 tgt, src, mask;
-
- REQUIRE_INSNS_FLAGS2(ctx, ISA310);
- REQUIRE_ALTIVEC(ctx);
-
- tgt = tcg_temp_new_i64();
- src = tcg_temp_new_i64();
- mask = tcg_temp_new_i64();
-
- /* centrifuge lower double word */
- get_cpu_vsrl(src, a->vra + 32);
- get_cpu_vsrl(mask, a->vrb + 32);
- gen_helper_cfuged(tgt, src, mask);
- set_cpu_vsrl(a->vrt + 32, tgt);
-
- /* centrifuge higher double word */
- get_cpu_vsrh(src, a->vra + 32);
- get_cpu_vsrh(mask, a->vrb + 32);
- gen_helper_cfuged(tgt, src, mask);
- set_cpu_vsrh(a->vrt + 32, tgt);
-
- tcg_temp_free_i64(tgt);
- tcg_temp_free_i64(src);
- tcg_temp_free_i64(mask);
-
- return true;
-}
diff --git a/target/ppc/translate/vmx-impl.c.inc b/target/ppc/translate/vmx-impl.c.inc
index 92b9527aff..b56e615c24 100644
--- a/target/ppc/translate/vmx-impl.c.inc
+++ b/target/ppc/translate/vmx-impl.c.inc
@@ -10,7 +10,7 @@
static inline TCGv_ptr gen_avr_ptr(int reg)
{
TCGv_ptr r = tcg_temp_new_ptr();
- tcg_gen_addi_ptr(r, cpu_env, avr_full_offset(reg));
+ tcg_gen_addi_ptr(r, tcg_env, avr_full_offset(reg));
return r;
}
@@ -45,8 +45,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
gen_qemu_ld64_i64(ctx, avr, EA); \
set_avr64(rD(ctx->opcode), avr, false); \
} \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(avr); \
}
#define GEN_VR_STX(name, opc2, opc3) \
@@ -80,8 +78,6 @@ static void gen_st##name(DisasContext *ctx) \
get_avr64(avr, rD(ctx->opcode), false); \
gen_qemu_st64_i64(ctx, avr, EA); \
} \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(avr); \
}
#define GEN_VR_LVE(name, opc2, opc3, size) \
@@ -100,9 +96,7 @@ static void gen_lve##name(DisasContext *ctx) \
tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
} \
rs = gen_avr_ptr(rS(ctx->opcode)); \
- gen_helper_lve##name(cpu_env, rs, EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_ptr(rs); \
+ gen_helper_lve##name(tcg_env, rs, EA); \
}
#define GEN_VR_STVE(name, opc2, opc3, size) \
@@ -121,13 +115,11 @@ static void gen_stve##name(DisasContext *ctx) \
tcg_gen_andi_tl(EA, EA, ~(size - 1)); \
} \
rs = gen_avr_ptr(rS(ctx->opcode)); \
- gen_helper_stve##name(cpu_env, rs, EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_ptr(rs); \
+ gen_helper_stve##name(tcg_env, rs, EA); \
}
GEN_VR_LDX(lvx, 0x07, 0x03);
-/* As we don't emulate the cache, lvxl is stricly equivalent to lvx */
+/* As we don't emulate the cache, lvxl is strictly equivalent to lvx */
GEN_VR_LDX(lvxl, 0x07, 0x0B);
GEN_VR_LVE(bx, 0x07, 0x00, 1);
@@ -135,7 +127,7 @@ GEN_VR_LVE(hx, 0x07, 0x01, 2);
GEN_VR_LVE(wx, 0x07, 0x02, 4);
GEN_VR_STX(svx, 0x07, 0x07);
-/* As we don't emulate the cache, stvxl is stricly equivalent to stvx */
+/* As we don't emulate the cache, stvxl is strictly equivalent to stvx */
GEN_VR_STX(svxl, 0x07, 0x0F);
GEN_VR_STVE(bx, 0x07, 0x04, 1);
@@ -154,11 +146,9 @@ static void gen_mfvscr(DisasContext *ctx)
tcg_gen_movi_i64(avr, 0);
set_avr64(rD(ctx->opcode), avr, true);
t = tcg_temp_new_i32();
- gen_helper_mfvscr(t, cpu_env);
+ gen_helper_mfvscr(t, tcg_env);
tcg_gen_extu_i32_i64(avr, t);
set_avr64(rD(ctx->opcode), avr, false);
- tcg_temp_free_i32(t);
- tcg_temp_free_i64(avr);
}
static void gen_mtvscr(DisasContext *ctx)
@@ -173,69 +163,64 @@ static void gen_mtvscr(DisasContext *ctx)
val = tcg_temp_new_i32();
bofs = avr_full_offset(rB(ctx->opcode));
-#ifdef HOST_WORDS_BIGENDIAN
+#if HOST_BIG_ENDIAN
bofs += 3 * 4;
#endif
- tcg_gen_ld_i32(val, cpu_env, bofs);
- gen_helper_mtvscr(cpu_env, val);
- tcg_temp_free_i32(val);
+ tcg_gen_ld_i32(val, tcg_env, bofs);
+ gen_helper_mtvscr(tcg_env, val);
+}
+
+static void gen_vx_vmul10(DisasContext *ctx, bool add_cin, bool ret_carry)
+{
+ TCGv_i64 t0;
+ TCGv_i64 t1;
+ TCGv_i64 t2;
+ TCGv_i64 avr;
+ TCGv_i64 ten, z;
+
+ if (unlikely(!ctx->altivec_enabled)) {
+ gen_exception(ctx, POWERPC_EXCP_VPU);
+ return;
+ }
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+ avr = tcg_temp_new_i64();
+ ten = tcg_constant_i64(10);
+ z = tcg_constant_i64(0);
+
+ if (add_cin) {
+ get_avr64(avr, rA(ctx->opcode), false);
+ tcg_gen_mulu2_i64(t0, t1, avr, ten);
+ get_avr64(avr, rB(ctx->opcode), false);
+ tcg_gen_andi_i64(t2, avr, 0xF);
+ tcg_gen_add2_i64(avr, t2, t0, t1, t2, z);
+ set_avr64(rD(ctx->opcode), avr, false);
+ } else {
+ get_avr64(avr, rA(ctx->opcode), false);
+ tcg_gen_mulu2_i64(avr, t2, avr, ten);
+ set_avr64(rD(ctx->opcode), avr, false);
+ }
+
+ if (ret_carry) {
+ get_avr64(avr, rA(ctx->opcode), true);
+ tcg_gen_mulu2_i64(t0, t1, avr, ten);
+ tcg_gen_add2_i64(t0, avr, t0, t1, t2, z);
+ set_avr64(rD(ctx->opcode), avr, false);
+ set_avr64(rD(ctx->opcode), z, true);
+ } else {
+ get_avr64(avr, rA(ctx->opcode), true);
+ tcg_gen_mul_i64(t0, avr, ten);
+ tcg_gen_add_i64(avr, t0, t2);
+ set_avr64(rD(ctx->opcode), avr, true);
+ }
}
#define GEN_VX_VMUL10(name, add_cin, ret_carry) \
-static void glue(gen_, name)(DisasContext *ctx) \
-{ \
- TCGv_i64 t0; \
- TCGv_i64 t1; \
- TCGv_i64 t2; \
- TCGv_i64 avr; \
- TCGv_i64 ten, z; \
- \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- \
- t0 = tcg_temp_new_i64(); \
- t1 = tcg_temp_new_i64(); \
- t2 = tcg_temp_new_i64(); \
- avr = tcg_temp_new_i64(); \
- ten = tcg_const_i64(10); \
- z = tcg_const_i64(0); \
- \
- if (add_cin) { \
- get_avr64(avr, rA(ctx->opcode), false); \
- tcg_gen_mulu2_i64(t0, t1, avr, ten); \
- get_avr64(avr, rB(ctx->opcode), false); \
- tcg_gen_andi_i64(t2, avr, 0xF); \
- tcg_gen_add2_i64(avr, t2, t0, t1, t2, z); \
- set_avr64(rD(ctx->opcode), avr, false); \
- } else { \
- get_avr64(avr, rA(ctx->opcode), false); \
- tcg_gen_mulu2_i64(avr, t2, avr, ten); \
- set_avr64(rD(ctx->opcode), avr, false); \
- } \
- \
- if (ret_carry) { \
- get_avr64(avr, rA(ctx->opcode), true); \
- tcg_gen_mulu2_i64(t0, t1, avr, ten); \
- tcg_gen_add2_i64(t0, avr, t0, t1, t2, z); \
- set_avr64(rD(ctx->opcode), avr, false); \
- set_avr64(rD(ctx->opcode), z, true); \
- } else { \
- get_avr64(avr, rA(ctx->opcode), true); \
- tcg_gen_mul_i64(t0, avr, ten); \
- tcg_gen_add_i64(avr, t0, t2); \
- set_avr64(rD(ctx->opcode), avr, true); \
- } \
- \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
- tcg_temp_free_i64(t2); \
- tcg_temp_free_i64(avr); \
- tcg_temp_free_i64(ten); \
- tcg_temp_free_i64(z); \
-} \
+ static void glue(gen_, name)(DisasContext *ctx) \
+ { gen_vx_vmul10(ctx, add_cin, ret_carry); }
GEN_VX_VMUL10(vmul10uq, 0, 0);
GEN_VX_VMUL10(vmul10euq, 1, 0);
@@ -279,9 +264,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
gen_helper_##name(rd, ra, rb); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
}
#define GEN_VXFORM_TRANS(name, opc2, opc3) \
@@ -305,10 +287,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
ra = gen_avr_ptr(rA(ctx->opcode)); \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name(cpu_env, rd, ra, rb); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ gen_helper_##name(tcg_env, rd, ra, rb); \
}
#define GEN_VXFORM3(name, opc2, opc3) \
@@ -324,10 +303,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
rc = gen_avr_ptr(rC(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
gen_helper_##name(rd, ra, rb, rc); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rc); \
- tcg_temp_free_ptr(rd); \
}
/*
@@ -400,7 +375,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
rb = gen_avr_ptr(rB(ctx->opcode)); \
gen_helper_##name(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], rb); \
- tcg_temp_free_ptr(rb); \
}
GEN_VXFORM_V(vaddubm, MO_8, tcg_gen_gvec_add, 0, 0);
@@ -431,21 +405,6 @@ GEN_VXFORM_V(vminsb, MO_8, tcg_gen_gvec_smin, 1, 12);
GEN_VXFORM_V(vminsh, MO_16, tcg_gen_gvec_smin, 1, 13);
GEN_VXFORM_V(vminsw, MO_32, tcg_gen_gvec_smin, 1, 14);
GEN_VXFORM_V(vminsd, MO_64, tcg_gen_gvec_smin, 1, 15);
-GEN_VXFORM(vavgub, 1, 16);
-GEN_VXFORM(vabsdub, 1, 16);
-GEN_VXFORM_DUAL(vavgub, PPC_ALTIVEC, PPC_NONE, \
- vabsdub, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vavguh, 1, 17);
-GEN_VXFORM(vabsduh, 1, 17);
-GEN_VXFORM_DUAL(vavguh, PPC_ALTIVEC, PPC_NONE, \
- vabsduh, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vavguw, 1, 18);
-GEN_VXFORM(vabsduw, 1, 18);
-GEN_VXFORM_DUAL(vavguw, PPC_ALTIVEC, PPC_NONE, \
- vabsduw, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM(vavgsb, 1, 20);
-GEN_VXFORM(vavgsh, 1, 21);
-GEN_VXFORM(vavgsw, 1, 22);
GEN_VXFORM(vmrghb, 6, 0);
GEN_VXFORM(vmrghh, 6, 1);
GEN_VXFORM(vmrghw, 6, 2);
@@ -472,9 +431,6 @@ static void trans_vmrgew(DisasContext *ctx)
get_avr64(avr, VA, false);
tcg_gen_deposit_i64(avr, avr, tmp, 0, 32);
set_avr64(VT, avr, false);
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(avr);
}
static void trans_vmrgow(DisasContext *ctx)
@@ -495,10 +451,6 @@ static void trans_vmrgow(DisasContext *ctx)
get_avr64(t1, VA, false);
tcg_gen_deposit_i64(avr, t0, t1, 32, 32);
set_avr64(VT, avr, false);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(avr);
}
/*
@@ -533,10 +485,6 @@ static void trans_lvsl(DisasContext *ctx)
*/
tcg_gen_addi_i64(result, sh, 0x08090a0b0c0d0e0fULL);
set_avr64(VT, result, false);
-
- tcg_temp_free_i64(result);
- tcg_temp_free_i64(sh);
- tcg_temp_free(EA);
}
/*
@@ -572,10 +520,6 @@ static void trans_lvsr(DisasContext *ctx)
*/
tcg_gen_subfi_i64(result, 0x18191a1b1c1d1e1fULL, sh);
set_avr64(VT, result, false);
-
- tcg_temp_free_i64(result);
- tcg_temp_free_i64(sh);
- tcg_temp_free(EA);
}
/*
@@ -618,11 +562,6 @@ static void trans_vsl(DisasContext *ctx)
tcg_gen_shl_i64(avr, avr, sh);
tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avr, true);
-
- tcg_temp_free_i64(avr);
- tcg_temp_free_i64(sh);
- tcg_temp_free_i64(carry);
- tcg_temp_free_i64(tmp);
}
/*
@@ -664,11 +603,6 @@ static void trans_vsr(DisasContext *ctx)
tcg_gen_shr_i64(avr, avr, sh);
tcg_gen_or_i64(avr, avr, carry);
set_avr64(VT, avr, false);
-
- tcg_temp_free_i64(avr);
- tcg_temp_free_i64(sh);
- tcg_temp_free_i64(carry);
- tcg_temp_free_i64(tmp);
}
/*
@@ -737,13 +671,6 @@ static void trans_vgbbd(DisasContext *ctx)
for (j = 0; j < 2; j++) {
set_avr64(VT, result[j], j);
}
-
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(tcg_mask);
- tcg_temp_free_i64(result[0]);
- tcg_temp_free_i64(result[1]);
- tcg_temp_free_i64(avr[0]);
- tcg_temp_free_i64(avr[1]);
}
/*
@@ -762,14 +689,12 @@ static void trans_vclzw(DisasContext *ctx)
/* Perform count for every word element using tcg_gen_clzi_i32. */
for (i = 0; i < 4; i++) {
- tcg_gen_ld_i32(tmp, cpu_env,
+ tcg_gen_ld_i32(tmp, tcg_env,
offsetof(CPUPPCState, vsr[32 + VB].u64[0]) + i * 4);
tcg_gen_clzi_i32(tmp, tmp, 32);
- tcg_gen_st_i32(tmp, cpu_env,
+ tcg_gen_st_i32(tmp, tcg_env,
offsetof(CPUPPCState, vsr[32 + VT].u64[0]) + i * 4);
}
-
- tcg_temp_free_i32(tmp);
}
/*
@@ -794,55 +719,360 @@ static void trans_vclzd(DisasContext *ctx)
get_avr64(avr, VB, false);
tcg_gen_clzi_i64(avr, avr, 64);
set_avr64(VT, avr, false);
-
- tcg_temp_free_i64(avr);
}
-GEN_VXFORM(vmuloub, 4, 0);
-GEN_VXFORM(vmulouh, 4, 1);
-GEN_VXFORM(vmulouw, 4, 2);
GEN_VXFORM_V(vmuluwm, MO_32, tcg_gen_gvec_mul, 4, 2);
-GEN_VXFORM_DUAL(vmulouw, PPC_ALTIVEC, PPC_NONE,
- vmuluwm, PPC_NONE, PPC2_ALTIVEC_207)
-GEN_VXFORM(vmulosb, 4, 4);
-GEN_VXFORM(vmulosh, 4, 5);
-GEN_VXFORM(vmulosw, 4, 6);
-GEN_VXFORM_V(vmulld, MO_64, tcg_gen_gvec_mul, 4, 7);
-GEN_VXFORM(vmuleub, 4, 8);
-GEN_VXFORM(vmuleuh, 4, 9);
-GEN_VXFORM(vmuleuw, 4, 10);
-GEN_VXFORM(vmulhuw, 4, 10);
-GEN_VXFORM(vmulhud, 4, 11);
-GEN_VXFORM_DUAL(vmuleuw, PPC_ALTIVEC, PPC_NONE,
- vmulhuw, PPC_NONE, PPC2_ISA310);
-GEN_VXFORM(vmulesb, 4, 12);
-GEN_VXFORM(vmulesh, 4, 13);
-GEN_VXFORM(vmulesw, 4, 14);
-GEN_VXFORM(vmulhsw, 4, 14);
-GEN_VXFORM_DUAL(vmulesw, PPC_ALTIVEC, PPC_NONE,
- vmulhsw, PPC_NONE, PPC2_ISA310);
-GEN_VXFORM(vmulhsd, 4, 15);
-GEN_VXFORM_V(vslb, MO_8, tcg_gen_gvec_shlv, 2, 4);
-GEN_VXFORM_V(vslh, MO_16, tcg_gen_gvec_shlv, 2, 5);
-GEN_VXFORM_V(vslw, MO_32, tcg_gen_gvec_shlv, 2, 6);
-GEN_VXFORM(vrlwnm, 2, 6);
-GEN_VXFORM_DUAL(vslw, PPC_ALTIVEC, PPC_NONE, \
- vrlwnm, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_V(vsld, MO_64, tcg_gen_gvec_shlv, 2, 23);
-GEN_VXFORM_V(vsrb, MO_8, tcg_gen_gvec_shrv, 2, 8);
-GEN_VXFORM_V(vsrh, MO_16, tcg_gen_gvec_shrv, 2, 9);
-GEN_VXFORM_V(vsrw, MO_32, tcg_gen_gvec_shrv, 2, 10);
-GEN_VXFORM_V(vsrd, MO_64, tcg_gen_gvec_shrv, 2, 27);
-GEN_VXFORM_V(vsrab, MO_8, tcg_gen_gvec_sarv, 2, 12);
-GEN_VXFORM_V(vsrah, MO_16, tcg_gen_gvec_sarv, 2, 13);
-GEN_VXFORM_V(vsraw, MO_32, tcg_gen_gvec_sarv, 2, 14);
-GEN_VXFORM_V(vsrad, MO_64, tcg_gen_gvec_sarv, 2, 15);
GEN_VXFORM(vsrv, 2, 28);
GEN_VXFORM(vslv, 2, 29);
GEN_VXFORM(vslo, 6, 16);
GEN_VXFORM(vsro, 6, 17);
-GEN_VXFORM(vaddcuw, 0, 6);
-GEN_VXFORM(vsubcuw, 0, 22);
+
+static bool do_vector_gvec3_VX(DisasContext *ctx, arg_VX *a, int vece,
+ void (*gen_gvec)(unsigned, uint32_t, uint32_t,
+ uint32_t, uint32_t, uint32_t))
+{
+ REQUIRE_VECTOR(ctx);
+
+ gen_gvec(vece, avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16);
+
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VSLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shlv);
+TRANS_FLAGS(ALTIVEC, VSLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shlv);
+TRANS_FLAGS(ALTIVEC, VSLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shlv);
+TRANS_FLAGS2(ALTIVEC_207, VSLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shlv);
+
+TRANS_FLAGS(ALTIVEC, VSRB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_shrv);
+TRANS_FLAGS(ALTIVEC, VSRH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_shrv);
+TRANS_FLAGS(ALTIVEC, VSRW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_shrv);
+TRANS_FLAGS2(ALTIVEC_207, VSRD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_shrv);
+
+TRANS_FLAGS(ALTIVEC, VSRAB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_sarv);
+TRANS_FLAGS(ALTIVEC, VSRAH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_sarv);
+TRANS_FLAGS(ALTIVEC, VSRAW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_sarv);
+TRANS_FLAGS2(ALTIVEC_207, VSRAD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_sarv);
+
+TRANS_FLAGS(ALTIVEC, VRLB, do_vector_gvec3_VX, MO_8, tcg_gen_gvec_rotlv)
+TRANS_FLAGS(ALTIVEC, VRLH, do_vector_gvec3_VX, MO_16, tcg_gen_gvec_rotlv)
+TRANS_FLAGS(ALTIVEC, VRLW, do_vector_gvec3_VX, MO_32, tcg_gen_gvec_rotlv)
+TRANS_FLAGS2(ALTIVEC_207, VRLD, do_vector_gvec3_VX, MO_64, tcg_gen_gvec_rotlv)
+
+static TCGv_vec do_vrl_mask_vec(unsigned vece, TCGv_vec vrb)
+{
+ TCGv_vec t0 = tcg_temp_new_vec_matching(vrb),
+ t1 = tcg_temp_new_vec_matching(vrb),
+ t2 = tcg_temp_new_vec_matching(vrb),
+ ones = tcg_constant_vec_matching(vrb, vece, -1);
+
+ /* Extract b and e */
+ tcg_gen_dupi_vec(vece, t2, (8 << vece) - 1);
+
+ tcg_gen_shri_vec(vece, t0, vrb, 16);
+ tcg_gen_and_vec(vece, t0, t0, t2);
+
+ tcg_gen_shri_vec(vece, t1, vrb, 8);
+ tcg_gen_and_vec(vece, t1, t1, t2);
+
+ /* Compare b and e to negate the mask where begin > end */
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, t2, t0, t1);
+
+ /* Create the mask with (~0 >> b) ^ ((~0 >> e) >> 1) */
+ tcg_gen_shrv_vec(vece, t0, ones, t0);
+ tcg_gen_shrv_vec(vece, t1, ones, t1);
+ tcg_gen_shri_vec(vece, t1, t1, 1);
+ tcg_gen_xor_vec(vece, t0, t0, t1);
+
+ /* negate the mask */
+ tcg_gen_xor_vec(vece, t0, t0, t2);
+
+ return t0;
+}
+
+static void gen_vrlnm_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
+ TCGv_vec vrb)
+{
+ TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt);
+
+ /* Create the mask */
+ mask = do_vrl_mask_vec(vece, vrb);
+
+ /* Extract n */
+ tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
+ tcg_gen_and_vec(vece, n, vrb, n);
+
+ /* Rotate and mask */
+ tcg_gen_rotlv_vec(vece, vrt, vra, n);
+ tcg_gen_and_vec(vece, vrt, vrt, mask);
+}
+
+static bool do_vrlnm(DisasContext *ctx, arg_VX *a, int vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
+ INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
+ };
+ static const GVecGen3 ops[2] = {
+ {
+ .fniv = gen_vrlnm_vec,
+ .fno = gen_helper_VRLWNM,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32
+ },
+ {
+ .fniv = gen_vrlnm_vec,
+ .fno = gen_helper_VRLDNM,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64
+ }
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
+
+ return true;
+}
+
+TRANS(VRLWNM, do_vrlnm, MO_32)
+TRANS(VRLDNM, do_vrlnm, MO_64)
+
+static void gen_vrlmi_vec(unsigned vece, TCGv_vec vrt, TCGv_vec vra,
+ TCGv_vec vrb)
+{
+ TCGv_vec mask, n = tcg_temp_new_vec_matching(vrt),
+ tmp = tcg_temp_new_vec_matching(vrt);
+
+ /* Create the mask */
+ mask = do_vrl_mask_vec(vece, vrb);
+
+ /* Extract n */
+ tcg_gen_dupi_vec(vece, n, (8 << vece) - 1);
+ tcg_gen_and_vec(vece, n, vrb, n);
+
+ /* Rotate and insert */
+ tcg_gen_rotlv_vec(vece, tmp, vra, n);
+ tcg_gen_bitsel_vec(vece, vrt, mask, tmp, vrt);
+}
+
+static bool do_vrlmi(DisasContext *ctx, arg_VX *a, int vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, INDEX_op_rotlv_vec, INDEX_op_sari_vec,
+ INDEX_op_shli_vec, INDEX_op_shri_vec, INDEX_op_shrv_vec, 0
+ };
+ static const GVecGen3 ops[2] = {
+ {
+ .fniv = gen_vrlmi_vec,
+ .fno = gen_helper_VRLWMI,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_32
+ },
+ {
+ .fniv = gen_vrlnm_vec,
+ .fno = gen_helper_VRLDMI,
+ .opt_opc = vecop_list,
+ .load_dest = true,
+ .vece = MO_64
+ }
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &ops[vece - 2]);
+
+ return true;
+}
+
+TRANS(VRLWMI, do_vrlmi, MO_32)
+TRANS(VRLDMI, do_vrlmi, MO_64)
+
+static bool do_vector_shift_quad(DisasContext *ctx, arg_VX *a, bool right,
+ bool alg)
+{
+ TCGv_i64 hi, lo, t0, t1, n, zero = tcg_constant_i64(0);
+
+ REQUIRE_VECTOR(ctx);
+
+ n = tcg_temp_new_i64();
+ hi = tcg_temp_new_i64();
+ lo = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+
+ get_avr64(lo, a->vra, false);
+ get_avr64(hi, a->vra, true);
+
+ get_avr64(n, a->vrb, true);
+
+ tcg_gen_andi_i64(t0, n, 64);
+ if (right) {
+ tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, hi, lo);
+ if (alg) {
+ t1 = tcg_temp_new_i64();
+ tcg_gen_sari_i64(t1, lo, 63);
+ } else {
+ t1 = zero;
+ }
+ tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, t1, hi);
+ } else {
+ tcg_gen_movcond_i64(TCG_COND_NE, hi, t0, zero, lo, hi);
+ tcg_gen_movcond_i64(TCG_COND_NE, lo, t0, zero, zero, lo);
+ }
+ tcg_gen_andi_i64(n, n, 0x3F);
+
+ if (right) {
+ if (alg) {
+ tcg_gen_sar_i64(t0, hi, n);
+ } else {
+ tcg_gen_shr_i64(t0, hi, n);
+ }
+ } else {
+ tcg_gen_shl_i64(t0, lo, n);
+ }
+ set_avr64(a->vrt, t0, right);
+
+ if (right) {
+ tcg_gen_shr_i64(lo, lo, n);
+ } else {
+ tcg_gen_shl_i64(hi, hi, n);
+ }
+ tcg_gen_xori_i64(n, n, 63);
+ if (right) {
+ tcg_gen_shl_i64(hi, hi, n);
+ tcg_gen_shli_i64(hi, hi, 1);
+ } else {
+ tcg_gen_shr_i64(lo, lo, n);
+ tcg_gen_shri_i64(lo, lo, 1);
+ }
+ tcg_gen_or_i64(hi, hi, lo);
+ set_avr64(a->vrt, hi, !right);
+ return true;
+}
+
+TRANS_FLAGS2(ISA310, VSLQ, do_vector_shift_quad, false, false);
+TRANS_FLAGS2(ISA310, VSRQ, do_vector_shift_quad, true, false);
+TRANS_FLAGS2(ISA310, VSRAQ, do_vector_shift_quad, true, true);
+
+static void do_vrlq_mask(TCGv_i64 mh, TCGv_i64 ml, TCGv_i64 b, TCGv_i64 e)
+{
+ TCGv_i64 th, tl, t0, t1, zero = tcg_constant_i64(0),
+ ones = tcg_constant_i64(-1);
+
+ th = tcg_temp_new_i64();
+ tl = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ /* m = ~0 >> b */
+ tcg_gen_andi_i64(t0, b, 64);
+ tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
+ tcg_gen_andi_i64(t0, b, 0x3F);
+ tcg_gen_shr_i64(mh, t1, t0);
+ tcg_gen_shr_i64(ml, ones, t0);
+ tcg_gen_xori_i64(t0, t0, 63);
+ tcg_gen_shl_i64(t1, t1, t0);
+ tcg_gen_shli_i64(t1, t1, 1);
+ tcg_gen_or_i64(ml, t1, ml);
+
+ /* t = ~0 >> e */
+ tcg_gen_andi_i64(t0, e, 64);
+ tcg_gen_movcond_i64(TCG_COND_NE, t1, t0, zero, zero, ones);
+ tcg_gen_andi_i64(t0, e, 0x3F);
+ tcg_gen_shr_i64(th, t1, t0);
+ tcg_gen_shr_i64(tl, ones, t0);
+ tcg_gen_xori_i64(t0, t0, 63);
+ tcg_gen_shl_i64(t1, t1, t0);
+ tcg_gen_shli_i64(t1, t1, 1);
+ tcg_gen_or_i64(tl, t1, tl);
+
+ /* t = t >> 1 */
+ tcg_gen_extract2_i64(tl, tl, th, 1);
+ tcg_gen_shri_i64(th, th, 1);
+
+ /* m = m ^ t */
+ tcg_gen_xor_i64(mh, mh, th);
+ tcg_gen_xor_i64(ml, ml, tl);
+
+ /* Negate the mask if begin > end */
+ tcg_gen_movcond_i64(TCG_COND_GT, t0, b, e, ones, zero);
+
+ tcg_gen_xor_i64(mh, mh, t0);
+ tcg_gen_xor_i64(ml, ml, t0);
+}
+
+static bool do_vector_rotl_quad(DisasContext *ctx, arg_VX *a, bool mask,
+ bool insert)
+{
+ TCGv_i64 ah, al, vrb, n, t0, t1, zero = tcg_constant_i64(0);
+
+ REQUIRE_VECTOR(ctx);
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+
+ ah = tcg_temp_new_i64();
+ al = tcg_temp_new_i64();
+ vrb = tcg_temp_new_i64();
+ n = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ get_avr64(ah, a->vra, true);
+ get_avr64(al, a->vra, false);
+ get_avr64(vrb, a->vrb, true);
+
+ tcg_gen_mov_i64(t0, ah);
+ tcg_gen_andi_i64(t1, vrb, 64);
+ tcg_gen_movcond_i64(TCG_COND_NE, ah, t1, zero, al, ah);
+ tcg_gen_movcond_i64(TCG_COND_NE, al, t1, zero, t0, al);
+ tcg_gen_andi_i64(n, vrb, 0x3F);
+
+ tcg_gen_shl_i64(t0, ah, n);
+ tcg_gen_shl_i64(t1, al, n);
+
+ tcg_gen_xori_i64(n, n, 63);
+
+ tcg_gen_shr_i64(al, al, n);
+ tcg_gen_shri_i64(al, al, 1);
+ tcg_gen_or_i64(t0, al, t0);
+
+ tcg_gen_shr_i64(ah, ah, n);
+ tcg_gen_shri_i64(ah, ah, 1);
+ tcg_gen_or_i64(t1, ah, t1);
+
+ if (mask || insert) {
+ tcg_gen_extract_i64(n, vrb, 8, 7);
+ tcg_gen_extract_i64(vrb, vrb, 16, 7);
+
+ do_vrlq_mask(ah, al, vrb, n);
+
+ tcg_gen_and_i64(t0, t0, ah);
+ tcg_gen_and_i64(t1, t1, al);
+
+ if (insert) {
+ get_avr64(n, a->vrt, true);
+ get_avr64(vrb, a->vrt, false);
+ tcg_gen_andc_i64(n, n, ah);
+ tcg_gen_andc_i64(vrb, vrb, al);
+ tcg_gen_or_i64(t0, t0, n);
+ tcg_gen_or_i64(t1, t1, vrb);
+ }
+ }
+
+ set_avr64(a->vrt, t0, true);
+ set_avr64(a->vrt, t1, false);
+ return true;
+}
+
+TRANS(VRLQ, do_vector_rotl_quad, false, false)
+TRANS(VRLQNM, do_vector_rotl_quad, true, false)
+TRANS(VRLQMI, do_vector_rotl_quad, false, true)
#define GEN_VXFORM_SAT(NAME, VECE, NORM, SAT, OPC2, OPC3) \
static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
@@ -854,7 +1084,6 @@ static void glue(glue(gen_, NAME), _vec)(unsigned vece, TCGv_vec t, \
glue(glue(tcg_gen_, SAT), _vec)(VECE, t, a, b); \
tcg_gen_cmp_vec(TCG_COND_NE, VECE, x, x, t); \
tcg_gen_or_vec(VECE, sat, sat, x); \
- tcg_temp_free_vec(x); \
} \
static void glue(gen_, NAME)(DisasContext *ctx) \
{ \
@@ -897,32 +1126,7 @@ GEN_VXFORM_SAT(vsubuws, MO_32, sub, ussub, 0, 26);
GEN_VXFORM_SAT(vsubsbs, MO_8, sub, sssub, 0, 28);
GEN_VXFORM_SAT(vsubshs, MO_16, sub, sssub, 0, 29);
GEN_VXFORM_SAT(vsubsws, MO_32, sub, sssub, 0, 30);
-GEN_VXFORM(vadduqm, 0, 4);
-GEN_VXFORM(vaddcuq, 0, 5);
-GEN_VXFORM3(vaddeuqm, 30, 0);
-GEN_VXFORM3(vaddecuq, 30, 0);
-GEN_VXFORM_DUAL(vaddeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
- vaddecuq, PPC_NONE, PPC2_ALTIVEC_207)
-GEN_VXFORM(vsubuqm, 0, 20);
-GEN_VXFORM(vsubcuq, 0, 21);
-GEN_VXFORM3(vsubeuqm, 31, 0);
-GEN_VXFORM3(vsubecuq, 31, 0);
-GEN_VXFORM_DUAL(vsubeuqm, PPC_NONE, PPC2_ALTIVEC_207, \
- vsubecuq, PPC_NONE, PPC2_ALTIVEC_207)
-GEN_VXFORM_V(vrlb, MO_8, tcg_gen_gvec_rotlv, 2, 0);
-GEN_VXFORM_V(vrlh, MO_16, tcg_gen_gvec_rotlv, 2, 1);
-GEN_VXFORM_V(vrlw, MO_32, tcg_gen_gvec_rotlv, 2, 2);
-GEN_VXFORM(vrlwmi, 2, 2);
-GEN_VXFORM_DUAL(vrlw, PPC_ALTIVEC, PPC_NONE, \
- vrlwmi, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_V(vrld, MO_64, tcg_gen_gvec_rotlv, 2, 3);
-GEN_VXFORM(vrldmi, 2, 3);
-GEN_VXFORM_DUAL(vrld, PPC_NONE, PPC2_ALTIVEC_207, \
- vrldmi, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_TRANS(vsl, 2, 7);
-GEN_VXFORM(vrldnm, 2, 7);
-GEN_VXFORM_DUAL(vsl, PPC_ALTIVEC, PPC_NONE, \
- vrldnm, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_TRANS(vsr, 2, 11);
GEN_VXFORM_ENV(vpkuhum, 7, 0);
GEN_VXFORM_ENV(vpkuwum, 7, 1);
@@ -970,10 +1174,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
ra = gen_avr_ptr(rA(ctx->opcode)); \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##opname(cpu_env, rd, ra, rb); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ gen_helper_##opname(tcg_env, rd, ra, rb); \
}
#define GEN_VXRFORM(name, opc2, opc3) \
@@ -982,7 +1183,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
/*
* Support for Altivec instructions that use bit 31 (Rc) as an opcode
- * bit but also use bit 21 as an actual Rc bit. In general, thse pairs
+ * bit but also use bit 21 as an actual Rc bit. In general, these pairs
* come from different versions of the ISA, so we must also support a
* pair of flags for each instruction.
*/
@@ -1008,41 +1209,230 @@ static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
} \
}
-GEN_VXRFORM(vcmpequb, 3, 0)
-GEN_VXRFORM(vcmpequh, 3, 1)
-GEN_VXRFORM(vcmpequw, 3, 2)
-GEN_VXRFORM(vcmpequd, 3, 3)
-GEN_VXRFORM(vcmpnezb, 3, 4)
-GEN_VXRFORM(vcmpnezh, 3, 5)
-GEN_VXRFORM(vcmpnezw, 3, 6)
-GEN_VXRFORM(vcmpgtsb, 3, 12)
-GEN_VXRFORM(vcmpgtsh, 3, 13)
-GEN_VXRFORM(vcmpgtsw, 3, 14)
-GEN_VXRFORM(vcmpgtsd, 3, 15)
-GEN_VXRFORM(vcmpgtub, 3, 8)
-GEN_VXRFORM(vcmpgtuh, 3, 9)
-GEN_VXRFORM(vcmpgtuw, 3, 10)
-GEN_VXRFORM(vcmpgtud, 3, 11)
+static void do_vcmp_rc(int vrt)
+{
+ TCGv_i64 tmp, set, clr;
+
+ tmp = tcg_temp_new_i64();
+ set = tcg_temp_new_i64();
+ clr = tcg_temp_new_i64();
+
+ get_avr64(tmp, vrt, true);
+ tcg_gen_mov_i64(set, tmp);
+ get_avr64(tmp, vrt, false);
+ tcg_gen_or_i64(clr, set, tmp);
+ tcg_gen_and_i64(set, set, tmp);
+
+ tcg_gen_setcondi_i64(TCG_COND_EQ, clr, clr, 0);
+ tcg_gen_shli_i64(clr, clr, 1);
+
+ tcg_gen_setcondi_i64(TCG_COND_EQ, set, set, -1);
+ tcg_gen_shli_i64(set, set, 3);
+
+ tcg_gen_or_i64(tmp, set, clr);
+ tcg_gen_extrl_i64_i32(cpu_crf[6], tmp);
+}
+
+static bool do_vcmp(DisasContext *ctx, arg_VC *a, TCGCond cond, int vece)
+{
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_cmp(cond, vece, avr_full_offset(a->vrt),
+ avr_full_offset(a->vra), avr_full_offset(a->vrb), 16, 16);
+
+ if (a->rc) {
+ do_vcmp_rc(a->vrt);
+ }
+
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VCMPEQUB, do_vcmp, TCG_COND_EQ, MO_8)
+TRANS_FLAGS(ALTIVEC, VCMPEQUH, do_vcmp, TCG_COND_EQ, MO_16)
+TRANS_FLAGS(ALTIVEC, VCMPEQUW, do_vcmp, TCG_COND_EQ, MO_32)
+TRANS_FLAGS2(ALTIVEC_207, VCMPEQUD, do_vcmp, TCG_COND_EQ, MO_64)
+
+TRANS_FLAGS(ALTIVEC, VCMPGTSB, do_vcmp, TCG_COND_GT, MO_8)
+TRANS_FLAGS(ALTIVEC, VCMPGTSH, do_vcmp, TCG_COND_GT, MO_16)
+TRANS_FLAGS(ALTIVEC, VCMPGTSW, do_vcmp, TCG_COND_GT, MO_32)
+TRANS_FLAGS2(ALTIVEC_207, VCMPGTSD, do_vcmp, TCG_COND_GT, MO_64)
+TRANS_FLAGS(ALTIVEC, VCMPGTUB, do_vcmp, TCG_COND_GTU, MO_8)
+TRANS_FLAGS(ALTIVEC, VCMPGTUH, do_vcmp, TCG_COND_GTU, MO_16)
+TRANS_FLAGS(ALTIVEC, VCMPGTUW, do_vcmp, TCG_COND_GTU, MO_32)
+TRANS_FLAGS2(ALTIVEC_207, VCMPGTUD, do_vcmp, TCG_COND_GTU, MO_64)
+
+TRANS_FLAGS2(ISA300, VCMPNEB, do_vcmp, TCG_COND_NE, MO_8)
+TRANS_FLAGS2(ISA300, VCMPNEH, do_vcmp, TCG_COND_NE, MO_16)
+TRANS_FLAGS2(ISA300, VCMPNEW, do_vcmp, TCG_COND_NE, MO_32)
+
+static void gen_vcmpnez_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ TCGv_vec t0, t1, zero;
+
+ t0 = tcg_temp_new_vec_matching(t);
+ t1 = tcg_temp_new_vec_matching(t);
+ zero = tcg_constant_vec_matching(t, vece, 0);
+
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t0, a, zero);
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t1, b, zero);
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, t, a, b);
+
+ tcg_gen_or_vec(vece, t, t, t0);
+ tcg_gen_or_vec(vece, t, t, t1);
+}
+
+static bool do_vcmpnez(DisasContext *ctx, arg_VC *a, int vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, 0
+ };
+ static const GVecGen3 ops[3] = {
+ {
+ .fniv = gen_vcmpnez_vec,
+ .fno = gen_helper_VCMPNEZB,
+ .opt_opc = vecop_list,
+ .vece = MO_8
+ },
+ {
+ .fniv = gen_vcmpnez_vec,
+ .fno = gen_helper_VCMPNEZH,
+ .opt_opc = vecop_list,
+ .vece = MO_16
+ },
+ {
+ .fniv = gen_vcmpnez_vec,
+ .fno = gen_helper_VCMPNEZW,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ }
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &ops[vece]);
+
+ if (a->rc) {
+ do_vcmp_rc(a->vrt);
+ }
+
+ return true;
+}
+
+TRANS(VCMPNEZB, do_vcmpnez, MO_8)
+TRANS(VCMPNEZH, do_vcmpnez, MO_16)
+TRANS(VCMPNEZW, do_vcmpnez, MO_32)
+
+static bool trans_VCMPEQUQ(DisasContext *ctx, arg_VC *a)
+{
+ TCGv_i64 t0, t1, t2;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+
+ get_avr64(t0, a->vra, true);
+ get_avr64(t1, a->vrb, true);
+ tcg_gen_xor_i64(t2, t0, t1);
+
+ get_avr64(t0, a->vra, false);
+ get_avr64(t1, a->vrb, false);
+ tcg_gen_xor_i64(t1, t0, t1);
+
+ tcg_gen_or_i64(t1, t1, t2);
+ tcg_gen_negsetcond_i64(TCG_COND_EQ, t1, t1, tcg_constant_i64(0));
+
+ set_avr64(a->vrt, t1, true);
+ set_avr64(a->vrt, t1, false);
+
+ if (a->rc) {
+ tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
+ tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
+ tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
+ }
+ return true;
+}
+
+static bool do_vcmpgtq(DisasContext *ctx, arg_VC *a, bool sign)
+{
+ TCGv_i64 t0, t1, t2;
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ t2 = tcg_temp_new_i64();
+
+ get_avr64(t0, a->vra, false);
+ get_avr64(t1, a->vrb, false);
+ tcg_gen_negsetcond_i64(TCG_COND_GTU, t2, t0, t1);
+
+ get_avr64(t0, a->vra, true);
+ get_avr64(t1, a->vrb, true);
+ tcg_gen_movcond_i64(TCG_COND_EQ, t2, t0, t1, t2, tcg_constant_i64(0));
+ tcg_gen_negsetcond_i64(sign ? TCG_COND_GT : TCG_COND_GTU, t1, t0, t1);
+
+ tcg_gen_or_i64(t1, t1, t2);
+
+ set_avr64(a->vrt, t1, true);
+ set_avr64(a->vrt, t1, false);
+
+ if (a->rc) {
+ tcg_gen_extrl_i64_i32(cpu_crf[6], t1);
+ tcg_gen_andi_i32(cpu_crf[6], cpu_crf[6], 0xa);
+ tcg_gen_xori_i32(cpu_crf[6], cpu_crf[6], 0x2);
+ }
+ return true;
+}
+
+TRANS(VCMPGTSQ, do_vcmpgtq, true)
+TRANS(VCMPGTUQ, do_vcmpgtq, false)
+
+static bool do_vcmpq(DisasContext *ctx, arg_VX_bf *a, bool sign)
+{
+ TCGv_i64 vra, vrb;
+ TCGLabel *gt, *lt, *done;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ vra = tcg_temp_new_i64();
+ vrb = tcg_temp_new_i64();
+ gt = gen_new_label();
+ lt = gen_new_label();
+ done = gen_new_label();
+
+ get_avr64(vra, a->vra, true);
+ get_avr64(vrb, a->vrb, true);
+ tcg_gen_brcond_i64((sign ? TCG_COND_GT : TCG_COND_GTU), vra, vrb, gt);
+ tcg_gen_brcond_i64((sign ? TCG_COND_LT : TCG_COND_LTU), vra, vrb, lt);
+
+ get_avr64(vra, a->vra, false);
+ get_avr64(vrb, a->vrb, false);
+ tcg_gen_brcond_i64(TCG_COND_GTU, vra, vrb, gt);
+ tcg_gen_brcond_i64(TCG_COND_LTU, vra, vrb, lt);
+
+ tcg_gen_movi_i32(cpu_crf[a->bf], CRF_EQ);
+ tcg_gen_br(done);
+
+ gen_set_label(gt);
+ tcg_gen_movi_i32(cpu_crf[a->bf], CRF_GT);
+ tcg_gen_br(done);
+
+ gen_set_label(lt);
+ tcg_gen_movi_i32(cpu_crf[a->bf], CRF_LT);
+ tcg_gen_br(done);
+
+ gen_set_label(done);
+ return true;
+}
+
+TRANS(VCMPSQ, do_vcmpq, true)
+TRANS(VCMPUQ, do_vcmpq, false)
+
GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
GEN_VXRFORM(vcmpgtfp, 3, 11)
GEN_VXRFORM(vcmpbfp, 3, 15)
-GEN_VXRFORM(vcmpneb, 3, 0)
-GEN_VXRFORM(vcmpneh, 3, 1)
-GEN_VXRFORM(vcmpnew, 3, 2)
-
-GEN_VXRFORM_DUAL(vcmpequb, PPC_ALTIVEC, PPC_NONE, \
- vcmpneb, PPC_NONE, PPC2_ISA300)
-GEN_VXRFORM_DUAL(vcmpequh, PPC_ALTIVEC, PPC_NONE, \
- vcmpneh, PPC_NONE, PPC2_ISA300)
-GEN_VXRFORM_DUAL(vcmpequw, PPC_ALTIVEC, PPC_NONE, \
- vcmpnew, PPC_NONE, PPC2_ISA300)
-GEN_VXRFORM_DUAL(vcmpeqfp, PPC_ALTIVEC, PPC_NONE, \
- vcmpequd, PPC_NONE, PPC2_ALTIVEC_207)
-GEN_VXRFORM_DUAL(vcmpbfp, PPC_ALTIVEC, PPC_NONE, \
- vcmpgtsd, PPC_NONE, PPC2_ALTIVEC_207)
-GEN_VXRFORM_DUAL(vcmpgtfp, PPC_ALTIVEC, PPC_NONE, \
- vcmpgtud, PPC_NONE, PPC2_ALTIVEC_207)
static void gen_vsplti(DisasContext *ctx, int vece)
{
@@ -1075,8 +1465,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
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); \
}
#define GEN_VXFORM_NOA_ENV(name, opc2, opc3) \
@@ -1090,9 +1478,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name(cpu_env, rd, rb); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ gen_helper_##name(tcg_env, rd, rb); \
}
#define GEN_VXFORM_NOA_2(name, opc2, opc3, opc4) \
@@ -1106,8 +1492,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
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); \
}
#define GEN_VXFORM_NOA_3(name, opc2, opc3, opc4) \
@@ -1120,7 +1504,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
rb = gen_avr_ptr(rB(ctx->opcode)); \
gen_helper_##name(cpu_gpr[rD(ctx->opcode)], rb); \
- tcg_temp_free_ptr(rb); \
}
GEN_VXFORM_NOA(vupkhsb, 7, 8);
GEN_VXFORM_NOA(vupkhsh, 7, 9);
@@ -1138,9 +1521,70 @@ GEN_VXFORM_NOA_ENV(vrfim, 5, 11);
GEN_VXFORM_NOA_ENV(vrfin, 5, 8);
GEN_VXFORM_NOA_ENV(vrfip, 5, 10);
GEN_VXFORM_NOA_ENV(vrfiz, 5, 9);
-GEN_VXFORM_NOA(vprtybw, 1, 24);
-GEN_VXFORM_NOA(vprtybd, 1, 24);
-GEN_VXFORM_NOA(vprtybq, 1, 24);
+
+static void gen_vprtyb_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ int i;
+ TCGv_vec tmp = tcg_temp_new_vec_matching(b);
+ /* MO_32 is 2, so 2 iterations for MO_32 and 3 for MO_64 */
+ for (i = 0; i < vece; i++) {
+ tcg_gen_shri_vec(vece, tmp, b, (4 << (vece - i)));
+ tcg_gen_xor_vec(vece, b, tmp, b);
+ }
+ tcg_gen_and_vec(vece, t, b, tcg_constant_vec_matching(t, vece, 1));
+}
+
+/* vprtybw */
+static void gen_vprtyb_i32(TCGv_i32 t, TCGv_i32 b)
+{
+ tcg_gen_ctpop_i32(t, b);
+ tcg_gen_and_i32(t, t, tcg_constant_i32(1));
+}
+
+/* vprtybd */
+static void gen_vprtyb_i64(TCGv_i64 t, TCGv_i64 b)
+{
+ tcg_gen_ctpop_i64(t, b);
+ tcg_gen_and_i64(t, t, tcg_constant_i64(1));
+}
+
+static bool do_vx_vprtyb(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shri_vec, 0
+ };
+
+ static const GVecGen2 op[] = {
+ {
+ .fniv = gen_vprtyb_vec,
+ .fni4 = gen_vprtyb_i32,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ {
+ .fniv = gen_vprtyb_vec,
+ .fni8 = gen_vprtyb_i64,
+ .opt_opc = vecop_list,
+ .vece = MO_64
+ },
+ {
+ .fno = gen_helper_VPRTYBQ,
+ .vece = MO_128
+ },
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_2(avr_full_offset(a->vrt), avr_full_offset(a->vrb),
+ 16, 16, &op[vece - MO_32]);
+
+ return true;
+}
+
+TRANS(VPRTYBW, do_vx_vprtyb, MO_32)
+TRANS(VPRTYBD, do_vx_vprtyb, MO_64)
+TRANS(VPRTYBQ, do_vx_vprtyb, MO_128)
static void gen_vsplt(DisasContext *ctx, int vece)
{
@@ -1157,7 +1601,7 @@ static void gen_vsplt(DisasContext *ctx, int vece)
/* Experimental testing shows that hardware masks the immediate. */
bofs += (uimm << vece) & 15;
-#ifndef HOST_WORDS_BIGENDIAN
+#if !HOST_BIG_ENDIAN
bofs ^= 15;
bofs &= ~((1 << vece) - 1);
#endif
@@ -1178,13 +1622,10 @@ static void glue(gen_, name)(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VPU); \
return; \
} \
- uimm = tcg_const_i32(UIMM5(ctx->opcode)); \
+ uimm = tcg_constant_i32(UIMM5(ctx->opcode)); \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- gen_helper_##name(cpu_env, rd, rb, uimm); \
- tcg_temp_free_i32(uimm); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
+ gen_helper_##name(tcg_env, rd, rb, uimm); \
}
#define GEN_VXFORM_UIMM_SPLAT(name, opc2, opc3, splat_max) \
@@ -1205,9 +1646,6 @@ static void glue(gen_, name)(DisasContext *ctx) \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
gen_helper_##name(rd, rb, t0); \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
}
GEN_VXFORM_VSPLT(vspltb, MO_8, 6, 8);
@@ -1217,10 +1655,6 @@ GEN_VXFORM_UIMM_SPLAT(vextractub, 6, 8, 15);
GEN_VXFORM_UIMM_SPLAT(vextractuh, 6, 9, 14);
GEN_VXFORM_UIMM_SPLAT(vextractuw, 6, 10, 12);
GEN_VXFORM_UIMM_SPLAT(vextractd, 6, 11, 8);
-GEN_VXFORM_UIMM_SPLAT(vinsertb, 6, 12, 15);
-GEN_VXFORM_UIMM_SPLAT(vinserth, 6, 13, 14);
-GEN_VXFORM_UIMM_SPLAT(vinsertw, 6, 14, 12);
-GEN_VXFORM_UIMM_SPLAT(vinsertd, 6, 15, 8);
GEN_VXFORM_UIMM_ENV(vcfux, 5, 12);
GEN_VXFORM_UIMM_ENV(vcfsx, 5, 13);
GEN_VXFORM_UIMM_ENV(vctuxs, 5, 14);
@@ -1231,12 +1665,292 @@ GEN_VXFORM_DUAL(vsplth, PPC_ALTIVEC, PPC_NONE,
vextractuh, PPC_NONE, PPC2_ISA300);
GEN_VXFORM_DUAL(vspltw, PPC_ALTIVEC, PPC_NONE,
vextractuw, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltisb, PPC_ALTIVEC, PPC_NONE,
- vinsertb, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
- vinserth, PPC_NONE, PPC2_ISA300);
-GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
- vinsertw, PPC_NONE, PPC2_ISA300);
+
+static bool trans_VGNB(DisasContext *ctx, arg_VX_n *a)
+{
+ /*
+ * Similar to do_vextractm, we'll use a sequence of mask-shift-or operations
+ * to gather the bits. The masks can be created with
+ *
+ * uint64_t mask(uint64_t n, uint64_t step)
+ * {
+ * uint64_t p = ((1UL << (1UL << step)) - 1UL) << ((n - 1UL) << step),
+ * plen = n << step, m = 0;
+ * for(int i = 0; i < 64/plen; i++) {
+ * m |= p;
+ * m = ror64(m, plen);
+ * }
+ * p >>= plen * DIV_ROUND_UP(64, plen) - 64;
+ * return m | p;
+ * }
+ *
+ * But since there are few values of N, we'll use a lookup table to avoid
+ * these calculations at runtime.
+ */
+ static const uint64_t mask[6][5] = {
+ {
+ 0xAAAAAAAAAAAAAAAAULL, 0xccccccccccccccccULL, 0xf0f0f0f0f0f0f0f0ULL,
+ 0xff00ff00ff00ff00ULL, 0xffff0000ffff0000ULL
+ },
+ {
+ 0x9249249249249249ULL, 0xC30C30C30C30C30CULL, 0xF00F00F00F00F00FULL,
+ 0xFF0000FF0000FF00ULL, 0xFFFF00000000FFFFULL
+ },
+ {
+ /* For N >= 4, some mask operations can be elided */
+ 0x8888888888888888ULL, 0, 0xf000f000f000f000ULL, 0,
+ 0xFFFF000000000000ULL
+ },
+ {
+ 0x8421084210842108ULL, 0, 0xF0000F0000F0000FULL, 0, 0
+ },
+ {
+ 0x8208208208208208ULL, 0, 0xF00000F00000F000ULL, 0, 0
+ },
+ {
+ 0x8102040810204081ULL, 0, 0xF000000F000000F0ULL, 0, 0
+ }
+ };
+ uint64_t m;
+ int i, sh, nbits = DIV_ROUND_UP(64, a->n);
+ TCGv_i64 hi, lo, t0, t1;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ if (a->n < 2) {
+ /*
+ * "N can be any value between 2 and 7, inclusive." Otherwise, the
+ * result is undefined, so we don't need to change RT. Also, N > 7 is
+ * impossible since the immediate field is 3 bits only.
+ */
+ return true;
+ }
+
+ hi = tcg_temp_new_i64();
+ lo = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ get_avr64(hi, a->vrb, true);
+ get_avr64(lo, a->vrb, false);
+
+ /* Align the lower doubleword so we can use the same mask */
+ tcg_gen_shli_i64(lo, lo, a->n * nbits - 64);
+
+ /*
+ * Starting from the most significant bit, gather every Nth bit with a
+ * sequence of mask-shift-or operation. E.g.: for N=3
+ * AxxBxxCxxDxxExxFxxGxxHxxIxxJxxKxxLxxMxxNxxOxxPxxQxxRxxSxxTxxUxxV
+ * & rep(0b100)
+ * A..B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V
+ * << 2
+ * .B..C..D..E..F..G..H..I..J..K..L..M..N..O..P..Q..R..S..T..U..V..
+ * |
+ * AB.BC.CD.DE.EF.FG.GH.HI.IJ.JK.KL.LM.MN.NO.OP.PQ.QR.RS.ST.TU.UV.V
+ * & rep(0b110000)
+ * AB....CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV..
+ * << 4
+ * ..CD....EF....GH....IJ....KL....MN....OP....QR....ST....UV......
+ * |
+ * ABCD..CDEF..EFGH..GHIJ..IJKL..KLMN..MNOP..OPQR..QRST..STUV..UV..
+ * & rep(0b111100000000)
+ * ABCD........EFGH........IJKL........MNOP........QRST........UV..
+ * << 8
+ * ....EFGH........IJKL........MNOP........QRST........UV..........
+ * |
+ * ABCDEFGH....EFGHIJKL....IJKLMNOP....MNOPQRST....QRSTUV......UV..
+ * & rep(0b111111110000000000000000)
+ * ABCDEFGH................IJKLMNOP................QRSTUV..........
+ * << 16
+ * ........IJKLMNOP................QRSTUV..........................
+ * |
+ * ABCDEFGHIJKLMNOP........IJKLMNOPQRSTUV..........QRSTUV..........
+ * & rep(0b111111111111111100000000000000000000000000000000)
+ * ABCDEFGHIJKLMNOP................................QRSTUV..........
+ * << 32
+ * ................QRSTUV..........................................
+ * |
+ * ABCDEFGHIJKLMNOPQRSTUV..........................QRSTUV..........
+ */
+ for (i = 0, sh = a->n - 1; i < 5; i++, sh <<= 1) {
+ m = mask[a->n - 2][i];
+ if (m) {
+ tcg_gen_andi_i64(hi, hi, m);
+ tcg_gen_andi_i64(lo, lo, m);
+ }
+ if (sh < 64) {
+ tcg_gen_shli_i64(t0, hi, sh);
+ tcg_gen_shli_i64(t1, lo, sh);
+ tcg_gen_or_i64(hi, t0, hi);
+ tcg_gen_or_i64(lo, t1, lo);
+ }
+ }
+
+ tcg_gen_andi_i64(hi, hi, ~(~0ULL >> nbits));
+ tcg_gen_andi_i64(lo, lo, ~(~0ULL >> nbits));
+ tcg_gen_shri_i64(lo, lo, nbits);
+ tcg_gen_or_i64(hi, hi, lo);
+ tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], hi);
+ return true;
+}
+
+static bool do_vextdx(DisasContext *ctx, arg_VA *a, int size, bool right,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv))
+{
+ TCGv_ptr vrt, vra, vrb;
+ TCGv rc;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ vrt = gen_avr_ptr(a->vrt);
+ vra = gen_avr_ptr(a->vra);
+ vrb = gen_avr_ptr(a->vrb);
+ rc = tcg_temp_new();
+
+ tcg_gen_andi_tl(rc, cpu_gpr[a->rc], 0x1F);
+ if (right) {
+ tcg_gen_subfi_tl(rc, 32 - size, rc);
+ }
+ gen_helper(tcg_env, vrt, vra, vrb, rc);
+ return true;
+}
+
+TRANS(VEXTDUBVLX, do_vextdx, 1, false, gen_helper_VEXTDUBVLX)
+TRANS(VEXTDUHVLX, do_vextdx, 2, false, gen_helper_VEXTDUHVLX)
+TRANS(VEXTDUWVLX, do_vextdx, 4, false, gen_helper_VEXTDUWVLX)
+TRANS(VEXTDDVLX, do_vextdx, 8, false, gen_helper_VEXTDDVLX)
+
+TRANS(VEXTDUBVRX, do_vextdx, 1, true, gen_helper_VEXTDUBVLX)
+TRANS(VEXTDUHVRX, do_vextdx, 2, true, gen_helper_VEXTDUHVLX)
+TRANS(VEXTDUWVRX, do_vextdx, 4, true, gen_helper_VEXTDUWVLX)
+TRANS(VEXTDDVRX, do_vextdx, 8, true, gen_helper_VEXTDDVLX)
+
+static bool do_vinsx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
+ TCGv_i64 rb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ TCGv_ptr t;
+ TCGv idx;
+
+ t = gen_avr_ptr(vrt);
+ idx = tcg_temp_new();
+
+ tcg_gen_andi_tl(idx, ra, 0xF);
+ if (right) {
+ tcg_gen_subfi_tl(idx, 16 - size, idx);
+ }
+
+ gen_helper(tcg_env, t, rb, idx);
+ return true;
+}
+
+static bool do_vinsvx(DisasContext *ctx, int vrt, int size, bool right, TCGv ra,
+ int vrb, void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ TCGv_i64 val;
+
+ val = tcg_temp_new_i64();
+ get_avr64(val, vrb, true);
+ return do_vinsx(ctx, vrt, size, right, ra, val, gen_helper);
+}
+
+static bool do_vinsx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ TCGv_i64 val;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ val = tcg_temp_new_i64();
+ tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
+
+ return do_vinsx(ctx, a->vrt, size, right, cpu_gpr[a->vra], val, gen_helper);
+}
+
+static bool do_vinsvx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ return do_vinsvx(ctx, a->vrt, size, right, cpu_gpr[a->vra], a->vrb,
+ gen_helper);
+}
+
+static bool do_vins_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ TCGv_i64 val;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ if (a->uim > (16 - size)) {
+ /*
+ * PowerISA v3.1 says that the resulting value is undefined in this
+ * case, so just log a guest error and leave VRT unchanged. The
+ * real hardware would do a partial insert, e.g. if VRT is zeroed and
+ * RB is 0x12345678, executing "vinsw VRT,RB,14" results in
+ * VRT = 0x0000...00001234, but we don't bother to reproduce this
+ * behavior as software shouldn't rely on it.
+ */
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINS* at"
+ " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
+ 16 - size);
+ return true;
+ }
+
+ val = tcg_temp_new_i64();
+ tcg_gen_extu_tl_i64(val, cpu_gpr[a->vrb]);
+
+ return do_vinsx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), val,
+ gen_helper);
+}
+
+static bool do_vinsert_VX_uim4(DisasContext *ctx, arg_VX_uim4 *a, int size,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ if (a->uim > (16 - size)) {
+ qemu_log_mask(LOG_GUEST_ERROR, "Invalid index for VINSERT* at"
+ " 0x" TARGET_FMT_lx ", UIM = %d > %d\n", ctx->cia, a->uim,
+ 16 - size);
+ return true;
+ }
+
+ return do_vinsvx(ctx, a->vrt, size, false, tcg_constant_tl(a->uim), a->vrb,
+ gen_helper);
+}
+
+TRANS(VINSBLX, do_vinsx_VX, 1, false, gen_helper_VINSBLX)
+TRANS(VINSHLX, do_vinsx_VX, 2, false, gen_helper_VINSHLX)
+TRANS(VINSWLX, do_vinsx_VX, 4, false, gen_helper_VINSWLX)
+TRANS(VINSDLX, do_vinsx_VX, 8, false, gen_helper_VINSDLX)
+
+TRANS(VINSBRX, do_vinsx_VX, 1, true, gen_helper_VINSBLX)
+TRANS(VINSHRX, do_vinsx_VX, 2, true, gen_helper_VINSHLX)
+TRANS(VINSWRX, do_vinsx_VX, 4, true, gen_helper_VINSWLX)
+TRANS(VINSDRX, do_vinsx_VX, 8, true, gen_helper_VINSDLX)
+
+TRANS(VINSW, do_vins_VX_uim4, 4, gen_helper_VINSWLX)
+TRANS(VINSD, do_vins_VX_uim4, 8, gen_helper_VINSDLX)
+
+TRANS(VINSBVLX, do_vinsvx_VX, 1, false, gen_helper_VINSBLX)
+TRANS(VINSHVLX, do_vinsvx_VX, 2, false, gen_helper_VINSHLX)
+TRANS(VINSWVLX, do_vinsvx_VX, 4, false, gen_helper_VINSWLX)
+
+TRANS(VINSBVRX, do_vinsvx_VX, 1, true, gen_helper_VINSBLX)
+TRANS(VINSHVRX, do_vinsvx_VX, 2, true, gen_helper_VINSHLX)
+TRANS(VINSWVRX, do_vinsvx_VX, 4, true, gen_helper_VINSWLX)
+
+TRANS(VINSERTB, do_vinsert_VX_uim4, 1, gen_helper_VINSBLX)
+TRANS(VINSERTH, do_vinsert_VX_uim4, 2, gen_helper_VINSHLX)
+TRANS(VINSERTW, do_vinsert_VX_uim4, 4, gen_helper_VINSWLX)
+TRANS(VINSERTD, do_vinsert_VX_uim4, 8, gen_helper_VINSDLX)
static void gen_vsldoi(DisasContext *ctx)
{
@@ -1249,14 +1963,379 @@ static void gen_vsldoi(DisasContext *ctx)
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));
+ sh = tcg_constant_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);
}
+static bool trans_VSLDBI(DisasContext *ctx, arg_VN *a)
+{
+ TCGv_i64 t0, t1, t2;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ get_avr64(t0, a->vra, true);
+ get_avr64(t1, a->vra, false);
+
+ if (a->sh != 0) {
+ t2 = tcg_temp_new_i64();
+
+ get_avr64(t2, a->vrb, true);
+
+ tcg_gen_extract2_i64(t0, t1, t0, 64 - a->sh);
+ tcg_gen_extract2_i64(t1, t2, t1, 64 - a->sh);
+ }
+
+ set_avr64(a->vrt, t0, true);
+ set_avr64(a->vrt, t1, false);
+ return true;
+}
+
+static bool trans_VSRDBI(DisasContext *ctx, arg_VN *a)
+{
+ TCGv_i64 t2, t1, t0;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ get_avr64(t0, a->vrb, false);
+ get_avr64(t1, a->vrb, true);
+
+ if (a->sh != 0) {
+ t2 = tcg_temp_new_i64();
+
+ get_avr64(t2, a->vra, false);
+
+ tcg_gen_extract2_i64(t0, t0, t1, a->sh);
+ tcg_gen_extract2_i64(t1, t1, t2, a->sh);
+ }
+
+ set_avr64(a->vrt, t0, false);
+ set_avr64(a->vrt, t1, true);
+ return true;
+}
+
+static bool do_vexpand(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_sari(vece, avr_full_offset(a->vrt), avr_full_offset(a->vrb),
+ (8 << vece) - 1, 16, 16);
+
+ return true;
+}
+
+TRANS(VEXPANDBM, do_vexpand, MO_8)
+TRANS(VEXPANDHM, do_vexpand, MO_16)
+TRANS(VEXPANDWM, do_vexpand, MO_32)
+TRANS(VEXPANDDM, do_vexpand, MO_64)
+
+static bool trans_VEXPANDQM(DisasContext *ctx, arg_VX_tb *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tmp = tcg_temp_new_i64();
+
+ get_avr64(tmp, a->vrb, true);
+ tcg_gen_sari_i64(tmp, tmp, 63);
+ set_avr64(a->vrt, tmp, false);
+ set_avr64(a->vrt, tmp, true);
+ return true;
+}
+
+static bool do_vextractm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+{
+ const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece,
+ mask = dup_const(vece, 1ULL << (elem_width - 1));
+ uint64_t i, j;
+ TCGv_i64 lo, hi, t0, t1;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ hi = tcg_temp_new_i64();
+ lo = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ get_avr64(lo, a->vrb, false);
+ get_avr64(hi, a->vrb, true);
+
+ tcg_gen_andi_i64(lo, lo, mask);
+ tcg_gen_andi_i64(hi, hi, mask);
+
+ /*
+ * Gather the most significant bit of each element in the highest element
+ * element. E.g. for bytes:
+ * aXXXXXXXbXXXXXXXcXXXXXXXdXXXXXXXeXXXXXXXfXXXXXXXgXXXXXXXhXXXXXXX
+ * & dup(1 << (elem_width - 1))
+ * a0000000b0000000c0000000d0000000e0000000f0000000g0000000h0000000
+ * << 32 - 4
+ * 0000e0000000f0000000g0000000h00000000000000000000000000000000000
+ * |
+ * a000e000b000f000c000g000d000h000e0000000f0000000g0000000h0000000
+ * << 16 - 2
+ * 00c000g000d000h000e0000000f0000000g0000000h000000000000000000000
+ * |
+ * a0c0e0g0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h0000000
+ * << 8 - 1
+ * 0b0d0f0h0c0e0g000d0f0h000e0g00000f0h00000g0000000h00000000000000
+ * |
+ * abcdefghbcdefgh0cdefgh00defgh000efgh0000fgh00000gh000000h0000000
+ */
+ for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
+ tcg_gen_shli_i64(t0, hi, j - i);
+ tcg_gen_shli_i64(t1, lo, j - i);
+ tcg_gen_or_i64(hi, hi, t0);
+ tcg_gen_or_i64(lo, lo, t1);
+ }
+
+ tcg_gen_shri_i64(hi, hi, 64 - elem_count_half);
+ tcg_gen_extract2_i64(lo, lo, hi, 64 - elem_count_half);
+ tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], lo);
+ return true;
+}
+
+TRANS(VEXTRACTBM, do_vextractm, MO_8)
+TRANS(VEXTRACTHM, do_vextractm, MO_16)
+TRANS(VEXTRACTWM, do_vextractm, MO_32)
+TRANS(VEXTRACTDM, do_vextractm, MO_64)
+
+static bool trans_VEXTRACTQM(DisasContext *ctx, arg_VX_tb *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tmp = tcg_temp_new_i64();
+
+ get_avr64(tmp, a->vrb, true);
+ tcg_gen_shri_i64(tmp, tmp, 63);
+ tcg_gen_trunc_i64_tl(cpu_gpr[a->vrt], tmp);
+ return true;
+}
+
+static bool do_mtvsrm(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+{
+ const uint64_t elem_width = 8 << vece, elem_count_half = 8 >> vece;
+ uint64_t c;
+ int i, j;
+ TCGv_i64 hi, lo, t0, t1;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ hi = tcg_temp_new_i64();
+ lo = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+
+ tcg_gen_extu_tl_i64(t0, cpu_gpr[a->vrb]);
+ tcg_gen_extract_i64(hi, t0, elem_count_half, elem_count_half);
+ tcg_gen_extract_i64(lo, t0, 0, elem_count_half);
+
+ /*
+ * Spread the bits into their respective elements.
+ * E.g. for bytes:
+ * 00000000000000000000000000000000000000000000000000000000abcdefgh
+ * << 32 - 4
+ * 0000000000000000000000000000abcdefgh0000000000000000000000000000
+ * |
+ * 0000000000000000000000000000abcdefgh00000000000000000000abcdefgh
+ * << 16 - 2
+ * 00000000000000abcdefgh00000000000000000000abcdefgh00000000000000
+ * |
+ * 00000000000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh
+ * << 8 - 1
+ * 0000000abcdefgh000000abcdefgh000000abcdefgh000000abcdefgh0000000
+ * |
+ * 0000000abcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgXbcdefgh
+ * & dup(1)
+ * 0000000a0000000b0000000c0000000d0000000e0000000f0000000g0000000h
+ * * 0xff
+ * aaaaaaaabbbbbbbbccccccccddddddddeeeeeeeeffffffffgggggggghhhhhhhh
+ */
+ for (i = elem_count_half / 2, j = 32; i > 0; i >>= 1, j >>= 1) {
+ tcg_gen_shli_i64(t0, hi, j - i);
+ tcg_gen_shli_i64(t1, lo, j - i);
+ tcg_gen_or_i64(hi, hi, t0);
+ tcg_gen_or_i64(lo, lo, t1);
+ }
+
+ c = dup_const(vece, 1);
+ tcg_gen_andi_i64(hi, hi, c);
+ tcg_gen_andi_i64(lo, lo, c);
+
+ c = MAKE_64BIT_MASK(0, elem_width);
+ tcg_gen_muli_i64(hi, hi, c);
+ tcg_gen_muli_i64(lo, lo, c);
+
+ set_avr64(a->vrt, lo, false);
+ set_avr64(a->vrt, hi, true);
+ return true;
+}
+
+TRANS(MTVSRBM, do_mtvsrm, MO_8)
+TRANS(MTVSRHM, do_mtvsrm, MO_16)
+TRANS(MTVSRWM, do_mtvsrm, MO_32)
+TRANS(MTVSRDM, do_mtvsrm, MO_64)
+
+static bool trans_MTVSRQM(DisasContext *ctx, arg_VX_tb *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tmp = tcg_temp_new_i64();
+
+ tcg_gen_ext_tl_i64(tmp, cpu_gpr[a->vrb]);
+ tcg_gen_sextract_i64(tmp, tmp, 0, 1);
+ set_avr64(a->vrt, tmp, false);
+ set_avr64(a->vrt, tmp, true);
+ return true;
+}
+
+static bool trans_MTVSRBMI(DisasContext *ctx, arg_DX_b *a)
+{
+ const uint64_t mask = dup_const(MO_8, 1);
+ uint64_t hi, lo;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ hi = extract16(a->b, 8, 8);
+ lo = extract16(a->b, 0, 8);
+
+ for (int i = 4, j = 32; i > 0; i >>= 1, j >>= 1) {
+ hi |= hi << (j - i);
+ lo |= lo << (j - i);
+ }
+
+ hi = (hi & mask) * 0xFF;
+ lo = (lo & mask) * 0xFF;
+
+ set_avr64(a->vrt, tcg_constant_i64(hi), true);
+ set_avr64(a->vrt, tcg_constant_i64(lo), false);
+
+ return true;
+}
+
+static bool do_vcntmb(DisasContext *ctx, arg_VX_mp *a, int vece)
+{
+ TCGv_i64 r[2], mask;
+
+ r[0] = tcg_temp_new_i64();
+ r[1] = tcg_temp_new_i64();
+ mask = tcg_constant_i64(dup_const(vece, 1ULL << ((8 << vece) - 1)));
+
+ for (int i = 0; i < 2; i++) {
+ get_avr64(r[i], a->vrb, i);
+ if (a->mp) {
+ tcg_gen_and_i64(r[i], mask, r[i]);
+ } else {
+ tcg_gen_andc_i64(r[i], mask, r[i]);
+ }
+ tcg_gen_ctpop_i64(r[i], r[i]);
+ }
+
+ tcg_gen_add_i64(r[0], r[0], r[1]);
+ tcg_gen_shli_i64(r[0], r[0], TARGET_LONG_BITS - 8 + vece);
+ tcg_gen_trunc_i64_tl(cpu_gpr[a->rt], r[0]);
+ return true;
+}
+
+TRANS(VCNTMBB, do_vcntmb, MO_8)
+TRANS(VCNTMBH, do_vcntmb, MO_16)
+TRANS(VCNTMBW, do_vcntmb, MO_32)
+TRANS(VCNTMBD, do_vcntmb, MO_64)
+
+static bool do_vstri(DisasContext *ctx, arg_VX_tb_rc *a,
+ void (*gen_helper)(TCGv_i32, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr vrt, vrb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ vrt = gen_avr_ptr(a->vrt);
+ vrb = gen_avr_ptr(a->vrb);
+
+ if (a->rc) {
+ gen_helper(cpu_crf[6], vrt, vrb);
+ } else {
+ TCGv_i32 discard = tcg_temp_new_i32();
+ gen_helper(discard, vrt, vrb);
+ }
+ return true;
+}
+
+TRANS(VSTRIBL, do_vstri, gen_helper_VSTRIBL)
+TRANS(VSTRIBR, do_vstri, gen_helper_VSTRIBR)
+TRANS(VSTRIHL, do_vstri, gen_helper_VSTRIHL)
+TRANS(VSTRIHR, do_vstri, gen_helper_VSTRIHR)
+
+static bool do_vclrb(DisasContext *ctx, arg_VX *a, bool right)
+{
+ TCGv_i64 rb, mh, ml, tmp,
+ ones = tcg_constant_i64(-1),
+ zero = tcg_constant_i64(0);
+
+ rb = tcg_temp_new_i64();
+ mh = tcg_temp_new_i64();
+ ml = tcg_temp_new_i64();
+ tmp = tcg_temp_new_i64();
+
+ tcg_gen_extu_tl_i64(rb, cpu_gpr[a->vrb]);
+ tcg_gen_andi_i64(tmp, rb, 7);
+ tcg_gen_shli_i64(tmp, tmp, 3);
+ if (right) {
+ tcg_gen_shr_i64(tmp, ones, tmp);
+ } else {
+ tcg_gen_shl_i64(tmp, ones, tmp);
+ }
+ tcg_gen_not_i64(tmp, tmp);
+
+ if (right) {
+ tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
+ tmp, ones);
+ tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
+ zero, tmp);
+ tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(16),
+ ml, ones);
+ } else {
+ tcg_gen_movcond_i64(TCG_COND_LTU, ml, rb, tcg_constant_i64(8),
+ tmp, ones);
+ tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(8),
+ zero, tmp);
+ tcg_gen_movcond_i64(TCG_COND_LTU, mh, rb, tcg_constant_i64(16),
+ mh, ones);
+ }
+
+ get_avr64(tmp, a->vra, true);
+ tcg_gen_and_i64(tmp, tmp, mh);
+ set_avr64(a->vrt, tmp, true);
+
+ get_avr64(tmp, a->vra, false);
+ tcg_gen_and_i64(tmp, tmp, ml);
+ set_avr64(a->vrt, tmp, false);
+ return true;
+}
+
+TRANS(VCLRLB, do_vclrb, false)
+TRANS(VCLRRB, do_vclrb, true)
+
#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
{ \
@@ -1270,71 +2349,190 @@ static void glue(gen_, name0##_##name1)(DisasContext *ctx) \
rc = gen_avr_ptr(rC(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
if (Rc(ctx->opcode)) { \
- gen_helper_##name1(cpu_env, rd, ra, rb, rc); \
+ gen_helper_##name1(tcg_env, rd, ra, rb, rc); \
} else { \
- gen_helper_##name0(cpu_env, rd, ra, rb, rc); \
+ gen_helper_##name0(tcg_env, 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_VAFORM_PAIRED(vmaddfp, vnmsubfp, 23)
-static void gen_vmladduhm(DisasContext *ctx)
+static bool do_va_helper(DisasContext *ctx, arg_VA *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
{
- 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);
+ TCGv_ptr vrt, vra, vrb, vrc;
+ REQUIRE_VECTOR(ctx);
+
+ vrt = gen_avr_ptr(a->vrt);
+ vra = gen_avr_ptr(a->vra);
+ vrb = gen_avr_ptr(a->vrb);
+ vrc = gen_avr_ptr(a->rc);
+ gen_helper(vrt, vra, vrb, vrc);
+ return true;
}
-static void gen_vpermr(DisasContext *ctx)
+TRANS_FLAGS2(ALTIVEC_207, VADDECUQ, do_va_helper, gen_helper_VADDECUQ)
+TRANS_FLAGS2(ALTIVEC_207, VADDEUQM, do_va_helper, gen_helper_VADDEUQM)
+
+TRANS_FLAGS2(ALTIVEC_207, VSUBEUQM, do_va_helper, gen_helper_VSUBEUQM)
+TRANS_FLAGS2(ALTIVEC_207, VSUBECUQ, do_va_helper, gen_helper_VSUBECUQ)
+
+TRANS_FLAGS(ALTIVEC, VPERM, do_va_helper, gen_helper_VPERM)
+TRANS_FLAGS2(ISA300, VPERMR, do_va_helper, gen_helper_VPERMR)
+
+static void gen_vmladduhm_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+ TCGv_vec c)
{
- 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_vpermr(cpu_env, rd, ra, rb, rc);
- tcg_temp_free_ptr(ra);
- tcg_temp_free_ptr(rb);
- tcg_temp_free_ptr(rc);
- tcg_temp_free_ptr(rd);
+ tcg_gen_mul_vec(vece, t, a, b);
+ tcg_gen_add_vec(vece, t, t, c);
}
-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)
+static bool trans_VMLADDUHM(DisasContext *ctx, arg_VA *a)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_add_vec, INDEX_op_mul_vec, 0
+ };
+
+ static const GVecGen4 op = {
+ .fno = gen_helper_VMLADDUHM,
+ .fniv = gen_vmladduhm_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_16
+ };
+
+ REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_4(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), avr_full_offset(a->rc),
+ 16, 16, &op);
+
+ return true;
+}
+
+static bool trans_VSEL(DisasContext *ctx, arg_VA *a)
+{
+ REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_bitsel(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->rc),
+ avr_full_offset(a->vrb), avr_full_offset(a->vra),
+ 16, 16);
+
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VMSUMUBM, do_va_helper, gen_helper_VMSUMUBM)
+TRANS_FLAGS(ALTIVEC, VMSUMMBM, do_va_helper, gen_helper_VMSUMMBM)
+TRANS_FLAGS(ALTIVEC, VMSUMSHM, do_va_helper, gen_helper_VMSUMSHM)
+TRANS_FLAGS(ALTIVEC, VMSUMUHM, do_va_helper, gen_helper_VMSUMUHM)
+
+static bool do_va_env_helper(DisasContext *ctx, arg_VA *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr vrt, vra, vrb, vrc;
+ REQUIRE_VECTOR(ctx);
+
+ vrt = gen_avr_ptr(a->vrt);
+ vra = gen_avr_ptr(a->vra);
+ vrb = gen_avr_ptr(a->vrb);
+ vrc = gen_avr_ptr(a->rc);
+ gen_helper(tcg_env, vrt, vra, vrb, vrc);
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VMSUMUHS, do_va_env_helper, gen_helper_VMSUMUHS)
+TRANS_FLAGS(ALTIVEC, VMSUMSHS, do_va_env_helper, gen_helper_VMSUMSHS)
+
+TRANS_FLAGS(ALTIVEC, VMHADDSHS, do_va_env_helper, gen_helper_VMHADDSHS)
+TRANS_FLAGS(ALTIVEC, VMHRADDSHS, do_va_env_helper, gen_helper_VMHRADDSHS)
GEN_VXFORM_NOA(vclzb, 1, 28)
GEN_VXFORM_NOA(vclzh, 1, 29)
GEN_VXFORM_TRANS(vclzw, 1, 30)
GEN_VXFORM_TRANS(vclzd, 1, 31)
-GEN_VXFORM_NOA_2(vnegw, 1, 24, 6)
-GEN_VXFORM_NOA_2(vnegd, 1, 24, 7)
-GEN_VXFORM_NOA_2(vextsb2w, 1, 24, 16)
-GEN_VXFORM_NOA_2(vextsh2w, 1, 24, 17)
-GEN_VXFORM_NOA_2(vextsb2d, 1, 24, 24)
-GEN_VXFORM_NOA_2(vextsh2d, 1, 24, 25)
-GEN_VXFORM_NOA_2(vextsw2d, 1, 24, 26)
+
+static bool do_vneg(DisasContext *ctx, arg_VX_tb *a, unsigned vece)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_neg(vece, avr_full_offset(a->vrt), avr_full_offset(a->vrb),
+ 16, 16);
+ return true;
+}
+
+TRANS(VNEGW, do_vneg, MO_32)
+TRANS(VNEGD, do_vneg, MO_64)
+
+static void gen_vexts_i64(TCGv_i64 t, TCGv_i64 b, int64_t s)
+{
+ tcg_gen_sextract_i64(t, b, 0, 64 - s);
+}
+
+static void gen_vexts_i32(TCGv_i32 t, TCGv_i32 b, int32_t s)
+{
+ tcg_gen_sextract_i32(t, b, 0, 32 - s);
+}
+
+static void gen_vexts_vec(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t s)
+{
+ tcg_gen_shli_vec(vece, t, b, s);
+ tcg_gen_sari_vec(vece, t, t, s);
+}
+
+static bool do_vexts(DisasContext *ctx, arg_VX_tb *a, unsigned vece, int64_t s)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_shli_vec, INDEX_op_sari_vec, 0
+ };
+
+ static const GVecGen2i op[2] = {
+ {
+ .fni4 = gen_vexts_i32,
+ .fniv = gen_vexts_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ {
+ .fni8 = gen_vexts_i64,
+ .fniv = gen_vexts_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_64
+ },
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_2i(avr_full_offset(a->vrt), avr_full_offset(a->vrb),
+ 16, 16, s, &op[vece - MO_32]);
+
+ return true;
+}
+
+TRANS(VEXTSB2W, do_vexts, MO_32, 24);
+TRANS(VEXTSH2W, do_vexts, MO_32, 16);
+TRANS(VEXTSB2D, do_vexts, MO_64, 56);
+TRANS(VEXTSH2D, do_vexts, MO_64, 48);
+TRANS(VEXTSW2D, do_vexts, MO_64, 32);
+
+static bool trans_VEXTSD2Q(DisasContext *ctx, arg_VX_tb *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tmp = tcg_temp_new_i64();
+
+ get_avr64(tmp, a->vrb, false);
+ set_avr64(a->vrt, tmp, false);
+ tcg_gen_sari_i64(tmp, tmp, 63);
+ set_avr64(a->vrt, tmp, true);
+ return true;
+}
+
GEN_VXFORM_NOA_2(vctzb, 1, 24, 28)
GEN_VXFORM_NOA_2(vctzh, 1, 24, 29)
GEN_VXFORM_NOA_2(vctzw, 1, 24, 30)
@@ -1359,7 +2557,6 @@ GEN_VXFORM_TRANS(vgbbd, 6, 20);
GEN_VXFORM(vpmsumb, 4, 16)
GEN_VXFORM(vpmsumh, 4, 17)
GEN_VXFORM(vpmsumw, 4, 18)
-GEN_VXFORM(vpmsumd, 4, 19)
#define GEN_BCD(op) \
static void gen_##op(DisasContext *ctx) \
@@ -1376,14 +2573,9 @@ static void gen_##op(DisasContext *ctx) \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
\
- ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
+ ps = tcg_constant_i32((ctx->opcode & 0x200) != 0); \
\
gen_helper_##op(cpu_crf[6], rd, ra, rb, ps); \
- \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
- tcg_temp_free_i32(ps); \
}
#define GEN_BCD2(op) \
@@ -1400,13 +2592,9 @@ static void gen_##op(DisasContext *ctx) \
rb = gen_avr_ptr(rB(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
\
- ps = tcg_const_i32((ctx->opcode & 0x200) != 0); \
+ ps = tcg_constant_i32((ctx->opcode & 0x200) != 0); \
\
gen_helper_##op(cpu_crf[6], rd, rb, ps); \
- \
- tcg_temp_free_ptr(rb); \
- tcg_temp_free_ptr(rd); \
- tcg_temp_free_i32(ps); \
}
GEN_BCD(bcdadd)
@@ -1483,8 +2671,6 @@ static void gen_xpnd04_2(DisasContext *ctx)
}
-GEN_VXFORM_DUAL(vsubcuw, PPC_ALTIVEC, PPC_NONE, \
- xpnd04_1, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_DUAL(vsubsws, PPC_ALTIVEC, PPC_NONE, \
xpnd04_2, PPC_NONE, PPC2_ISA300)
@@ -1504,11 +2690,6 @@ GEN_VXFORM_DUAL(vsubuwm, PPC_ALTIVEC, PPC_NONE, \
bcdus, PPC_NONE, PPC2_ISA300)
GEN_VXFORM_DUAL(vsubsbs, PPC_ALTIVEC, PPC_NONE, \
bcdtrunc, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_DUAL(vsubuqm, PPC2_ALTIVEC_207, PPC_NONE, \
- bcdtrunc, PPC_NONE, PPC2_ISA300)
-GEN_VXFORM_DUAL(vsubcuq, PPC2_ALTIVEC_207, PPC_NONE, \
- bcdutrunc, PPC_NONE, PPC2_ISA300)
-
static void gen_vsbox(DisasContext *ctx)
{
@@ -1520,8 +2701,6 @@ static void gen_vsbox(DisasContext *ctx)
ra = gen_avr_ptr(rA(ctx->opcode));
rd = gen_avr_ptr(rD(ctx->opcode));
gen_helper_vsbox(rd, ra);
- tcg_temp_free_ptr(ra);
- tcg_temp_free_ptr(rd);
}
GEN_VXFORM(vcipher, 4, 20)
@@ -1545,11 +2724,8 @@ static void gen_##op(DisasContext *ctx) \
} \
ra = gen_avr_ptr(rA(ctx->opcode)); \
rd = gen_avr_ptr(rD(ctx->opcode)); \
- st_six = tcg_const_i32(rB(ctx->opcode)); \
+ st_six = tcg_constant_i32(rB(ctx->opcode)); \
gen_helper_##op(rd, ra, st_six); \
- tcg_temp_free_ptr(ra); \
- tcg_temp_free_ptr(rd); \
- tcg_temp_free_i32(st_six); \
}
VSHASIGMA(vshasigmaw)
@@ -1559,6 +2735,636 @@ GEN_VXFORM3(vpermxor, 22, 0xFF)
GEN_VXFORM_DUAL(vsldoi, PPC_ALTIVEC, PPC_NONE,
vpermxor, PPC_NONE, PPC2_ALTIVEC_207)
+static bool trans_VCFUGED(DisasContext *ctx, arg_VX *a)
+{
+ static const GVecGen3 g = {
+ .fni8 = gen_helper_CFUGED,
+ .vece = MO_64,
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &g);
+
+ return true;
+}
+
+static bool trans_VCLZDM(DisasContext *ctx, arg_VX *a)
+{
+ static const GVecGen3i g = {
+ .fni8 = do_cntzdm,
+ .vece = MO_64,
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, false, &g);
+
+ return true;
+}
+
+static bool trans_VCTZDM(DisasContext *ctx, arg_VX *a)
+{
+ static const GVecGen3i g = {
+ .fni8 = do_cntzdm,
+ .vece = MO_64,
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3i(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, true, &g);
+
+ return true;
+}
+
+static bool trans_VPDEPD(DisasContext *ctx, arg_VX *a)
+{
+ static const GVecGen3 g = {
+ .fni8 = gen_helper_PDEPD,
+ .vece = MO_64,
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &g);
+
+ return true;
+}
+
+static bool trans_VPEXTD(DisasContext *ctx, arg_VX *a)
+{
+ static const GVecGen3 g = {
+ .fni8 = gen_helper_PEXTD,
+ .vece = MO_64,
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &g);
+
+ return true;
+}
+
+static bool trans_VMSUMUDM(DisasContext *ctx, arg_VA *a)
+{
+ TCGv_i64 rl, rh, src1, src2;
+ int dw;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VECTOR(ctx);
+
+ rh = tcg_temp_new_i64();
+ rl = tcg_temp_new_i64();
+ src1 = tcg_temp_new_i64();
+ src2 = tcg_temp_new_i64();
+
+ get_avr64(rl, a->rc, false);
+ get_avr64(rh, a->rc, true);
+
+ for (dw = 0; dw < 2; dw++) {
+ get_avr64(src1, a->vra, dw);
+ get_avr64(src2, a->vrb, dw);
+ tcg_gen_mulu2_i64(src1, src2, src1, src2);
+ tcg_gen_add2_i64(rl, rh, rl, rh, src1, src2);
+ }
+
+ set_avr64(a->vrt, rl, false);
+ set_avr64(a->vrt, rh, true);
+ return true;
+}
+
+static bool trans_VMSUMCUD(DisasContext *ctx, arg_VA *a)
+{
+ TCGv_i64 tmp0, tmp1, prod1h, prod1l, prod0h, prod0l, zero;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tmp0 = tcg_temp_new_i64();
+ tmp1 = tcg_temp_new_i64();
+ prod1h = tcg_temp_new_i64();
+ prod1l = tcg_temp_new_i64();
+ prod0h = tcg_temp_new_i64();
+ prod0l = tcg_temp_new_i64();
+ zero = tcg_constant_i64(0);
+
+ /* prod1 = vsr[vra+32].dw[1] * vsr[vrb+32].dw[1] */
+ get_avr64(tmp0, a->vra, false);
+ get_avr64(tmp1, a->vrb, false);
+ tcg_gen_mulu2_i64(prod1l, prod1h, tmp0, tmp1);
+
+ /* prod0 = vsr[vra+32].dw[0] * vsr[vrb+32].dw[0] */
+ get_avr64(tmp0, a->vra, true);
+ get_avr64(tmp1, a->vrb, true);
+ tcg_gen_mulu2_i64(prod0l, prod0h, tmp0, tmp1);
+
+ /* Sum lower 64-bits elements */
+ get_avr64(tmp1, a->rc, false);
+ tcg_gen_add2_i64(tmp1, tmp0, tmp1, zero, prod1l, zero);
+ tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0l, zero);
+
+ /*
+ * Discard lower 64-bits, leaving the carry into bit 64.
+ * Then sum the higher 64-bit elements.
+ */
+ get_avr64(tmp1, a->rc, true);
+ tcg_gen_add2_i64(tmp1, tmp0, tmp0, zero, tmp1, zero);
+ tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod1h, zero);
+ tcg_gen_add2_i64(tmp1, tmp0, tmp1, tmp0, prod0h, zero);
+
+ /* Discard 64 more bits to complete the CHOP128(temp >> 128) */
+ set_avr64(a->vrt, tmp0, false);
+ set_avr64(a->vrt, zero, true);
+ return true;
+}
+
+static bool do_vx_helper(DisasContext *ctx, arg_VX *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr ra, rb, rd;
+ REQUIRE_VECTOR(ctx);
+
+ ra = gen_avr_ptr(a->vra);
+ rb = gen_avr_ptr(a->vrb);
+ rd = gen_avr_ptr(a->vrt);
+ gen_helper(rd, ra, rb);
+ return true;
+}
+
+TRANS_FLAGS2(ALTIVEC_207, VADDCUQ, do_vx_helper, gen_helper_VADDCUQ)
+TRANS_FLAGS2(ALTIVEC_207, VADDUQM, do_vx_helper, gen_helper_VADDUQM)
+
+TRANS_FLAGS2(ALTIVEC_207, VPMSUMD, do_vx_helper, gen_helper_VPMSUMD)
+
+TRANS_FLAGS2(ALTIVEC_207, VSUBCUQ, do_vx_helper, gen_helper_VSUBCUQ)
+TRANS_FLAGS2(ALTIVEC_207, VSUBUQM, do_vx_helper, gen_helper_VSUBUQM)
+
+static void gen_VADDCUW_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ tcg_gen_not_vec(vece, a, a);
+ tcg_gen_cmp_vec(TCG_COND_LTU, vece, t, a, b);
+ tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(t, vece, 1));
+}
+
+static void gen_VADDCUW_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
+{
+ tcg_gen_not_i32(a, a);
+ tcg_gen_setcond_i32(TCG_COND_LTU, t, a, b);
+}
+
+static void gen_VSUBCUW_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ tcg_gen_cmp_vec(TCG_COND_GEU, vece, t, a, b);
+ tcg_gen_and_vec(vece, t, t, tcg_constant_vec_matching(t, vece, 1));
+}
+
+static void gen_VSUBCUW_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
+{
+ tcg_gen_setcond_i32(TCG_COND_GEU, t, a, b);
+}
+
+static bool do_vx_vaddsubcuw(DisasContext *ctx, arg_VX *a, int add)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, 0
+ };
+
+ static const GVecGen3 op[] = {
+ {
+ .fniv = gen_VSUBCUW_vec,
+ .fni4 = gen_VSUBCUW_i32,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ {
+ .fniv = gen_VADDCUW_vec,
+ .fni4 = gen_VADDCUW_i32,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ };
+
+ REQUIRE_INSNS_FLAGS(ctx, ALTIVEC);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &op[add]);
+
+ return true;
+}
+
+TRANS(VSUBCUW, do_vx_vaddsubcuw, 0)
+TRANS(VADDCUW, do_vx_vaddsubcuw, 1)
+
+static bool do_vx_vmuleo(DisasContext *ctx, arg_VX *a, bool even,
+ void (*gen_mul)(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_i64))
+{
+ TCGv_i64 vra, vrb, vrt0, vrt1;
+ REQUIRE_VECTOR(ctx);
+
+ vra = tcg_temp_new_i64();
+ vrb = tcg_temp_new_i64();
+ vrt0 = tcg_temp_new_i64();
+ vrt1 = tcg_temp_new_i64();
+
+ get_avr64(vra, a->vra, even);
+ get_avr64(vrb, a->vrb, even);
+ gen_mul(vrt0, vrt1, vra, vrb);
+ set_avr64(a->vrt, vrt0, false);
+ set_avr64(a->vrt, vrt1, true);
+ return true;
+}
+
+static bool trans_VMULLD(DisasContext *ctx, arg_VX *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_mul(MO_64, avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16);
+
+ return true;
+}
+
+TRANS_FLAGS(ALTIVEC, VMULESB, do_vx_helper, gen_helper_VMULESB)
+TRANS_FLAGS(ALTIVEC, VMULOSB, do_vx_helper, gen_helper_VMULOSB)
+TRANS_FLAGS(ALTIVEC, VMULEUB, do_vx_helper, gen_helper_VMULEUB)
+TRANS_FLAGS(ALTIVEC, VMULOUB, do_vx_helper, gen_helper_VMULOUB)
+TRANS_FLAGS(ALTIVEC, VMULESH, do_vx_helper, gen_helper_VMULESH)
+TRANS_FLAGS(ALTIVEC, VMULOSH, do_vx_helper, gen_helper_VMULOSH)
+TRANS_FLAGS(ALTIVEC, VMULEUH, do_vx_helper, gen_helper_VMULEUH)
+TRANS_FLAGS(ALTIVEC, VMULOUH, do_vx_helper, gen_helper_VMULOUH)
+TRANS_FLAGS2(ALTIVEC_207, VMULESW, do_vx_helper, gen_helper_VMULESW)
+TRANS_FLAGS2(ALTIVEC_207, VMULOSW, do_vx_helper, gen_helper_VMULOSW)
+TRANS_FLAGS2(ALTIVEC_207, VMULEUW, do_vx_helper, gen_helper_VMULEUW)
+TRANS_FLAGS2(ALTIVEC_207, VMULOUW, do_vx_helper, gen_helper_VMULOUW)
+TRANS_FLAGS2(ISA310, VMULESD, do_vx_vmuleo, true , tcg_gen_muls2_i64)
+TRANS_FLAGS2(ISA310, VMULOSD, do_vx_vmuleo, false, tcg_gen_muls2_i64)
+TRANS_FLAGS2(ISA310, VMULEUD, do_vx_vmuleo, true , tcg_gen_mulu2_i64)
+TRANS_FLAGS2(ISA310, VMULOUD, do_vx_vmuleo, false, tcg_gen_mulu2_i64)
+
+static void do_vx_vmulhw_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
+{
+ TCGv_i64 hh, lh, temp;
+
+ hh = tcg_temp_new_i64();
+ lh = tcg_temp_new_i64();
+ temp = tcg_temp_new_i64();
+
+ if (sign) {
+ tcg_gen_ext32s_i64(lh, a);
+ tcg_gen_ext32s_i64(temp, b);
+ } else {
+ tcg_gen_ext32u_i64(lh, a);
+ tcg_gen_ext32u_i64(temp, b);
+ }
+ tcg_gen_mul_i64(lh, lh, temp);
+
+ if (sign) {
+ tcg_gen_sari_i64(hh, a, 32);
+ tcg_gen_sari_i64(temp, b, 32);
+ } else {
+ tcg_gen_shri_i64(hh, a, 32);
+ tcg_gen_shri_i64(temp, b, 32);
+ }
+ tcg_gen_mul_i64(hh, hh, temp);
+
+ tcg_gen_shri_i64(lh, lh, 32);
+ tcg_gen_deposit_i64(t, hh, lh, 0, 32);
+}
+
+static void do_vx_vmulhd_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, bool sign)
+{
+ TCGv_i64 tlow;
+
+ tlow = tcg_temp_new_i64();
+ if (sign) {
+ tcg_gen_muls2_i64(tlow, t, a, b);
+ } else {
+ tcg_gen_mulu2_i64(tlow, t, a, b);
+ }
+}
+
+static bool do_vx_mulh(DisasContext *ctx, arg_VX *a, bool sign,
+ void (*func)(TCGv_i64, TCGv_i64, TCGv_i64, bool))
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VECTOR(ctx);
+
+ TCGv_i64 vra, vrb, vrt;
+ int i;
+
+ vra = tcg_temp_new_i64();
+ vrb = tcg_temp_new_i64();
+ vrt = tcg_temp_new_i64();
+
+ for (i = 0; i < 2; i++) {
+ get_avr64(vra, a->vra, i);
+ get_avr64(vrb, a->vrb, i);
+ get_avr64(vrt, a->vrt, i);
+
+ func(vrt, vra, vrb, sign);
+
+ set_avr64(a->vrt, vrt, i);
+ }
+ return true;
+}
+
+TRANS(VMULHSW, do_vx_mulh, true , do_vx_vmulhw_i64)
+TRANS(VMULHSD, do_vx_mulh, true , do_vx_vmulhd_i64)
+TRANS(VMULHUW, do_vx_mulh, false, do_vx_vmulhw_i64)
+TRANS(VMULHUD, do_vx_mulh, false, do_vx_vmulhd_i64)
+
+static void do_vavg(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+ void (*gen_shr_vec)(unsigned, TCGv_vec, TCGv_vec, int64_t))
+{
+ TCGv_vec tmp = tcg_temp_new_vec_matching(t);
+ tcg_gen_or_vec(vece, tmp, a, b);
+ tcg_gen_and_vec(vece, tmp, tmp, tcg_constant_vec_matching(t, vece, 1));
+ gen_shr_vec(vece, a, a, 1);
+ gen_shr_vec(vece, b, b, 1);
+ tcg_gen_add_vec(vece, t, a, b);
+ tcg_gen_add_vec(vece, t, t, tmp);
+}
+
+QEMU_FLATTEN
+static void gen_vavgu(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ do_vavg(vece, t, a, b, tcg_gen_shri_vec);
+}
+
+QEMU_FLATTEN
+static void gen_vavgs(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ do_vavg(vece, t, a, b, tcg_gen_sari_vec);
+}
+
+static bool do_vx_vavg(DisasContext *ctx, arg_VX *a, int sign, int vece)
+{
+ static const TCGOpcode vecop_list_s[] = {
+ INDEX_op_add_vec, INDEX_op_sari_vec, 0
+ };
+ static const TCGOpcode vecop_list_u[] = {
+ INDEX_op_add_vec, INDEX_op_shri_vec, 0
+ };
+
+ static const GVecGen3 op[2][3] = {
+ {
+ {
+ .fniv = gen_vavgu,
+ .fno = gen_helper_VAVGUB,
+ .opt_opc = vecop_list_u,
+ .vece = MO_8
+ },
+ {
+ .fniv = gen_vavgu,
+ .fno = gen_helper_VAVGUH,
+ .opt_opc = vecop_list_u,
+ .vece = MO_16
+ },
+ {
+ .fniv = gen_vavgu,
+ .fno = gen_helper_VAVGUW,
+ .opt_opc = vecop_list_u,
+ .vece = MO_32
+ },
+ },
+ {
+ {
+ .fniv = gen_vavgs,
+ .fno = gen_helper_VAVGSB,
+ .opt_opc = vecop_list_s,
+ .vece = MO_8
+ },
+ {
+ .fniv = gen_vavgs,
+ .fno = gen_helper_VAVGSH,
+ .opt_opc = vecop_list_s,
+ .vece = MO_16
+ },
+ {
+ .fniv = gen_vavgs,
+ .fno = gen_helper_VAVGSW,
+ .opt_opc = vecop_list_s,
+ .vece = MO_32
+ },
+ },
+ };
+
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &op[sign][vece]);
+
+
+ return true;
+}
+
+
+TRANS_FLAGS(ALTIVEC, VAVGSB, do_vx_vavg, 1, MO_8)
+TRANS_FLAGS(ALTIVEC, VAVGSH, do_vx_vavg, 1, MO_16)
+TRANS_FLAGS(ALTIVEC, VAVGSW, do_vx_vavg, 1, MO_32)
+TRANS_FLAGS(ALTIVEC, VAVGUB, do_vx_vavg, 0, MO_8)
+TRANS_FLAGS(ALTIVEC, VAVGUH, do_vx_vavg, 0, MO_16)
+TRANS_FLAGS(ALTIVEC, VAVGUW, do_vx_vavg, 0, MO_32)
+
+static void gen_vabsdu(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ tcg_gen_umax_vec(vece, t, a, b);
+ tcg_gen_umin_vec(vece, a, a, b);
+ tcg_gen_sub_vec(vece, t, t, a);
+}
+
+static bool do_vabsdu(DisasContext *ctx, arg_VX *a, const int vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_umax_vec, INDEX_op_umin_vec, INDEX_op_sub_vec, 0
+ };
+
+ static const GVecGen3 op[] = {
+ {
+ .fniv = gen_vabsdu,
+ .fno = gen_helper_VABSDUB,
+ .opt_opc = vecop_list,
+ .vece = MO_8
+ },
+ {
+ .fniv = gen_vabsdu,
+ .fno = gen_helper_VABSDUH,
+ .opt_opc = vecop_list,
+ .vece = MO_16
+ },
+ {
+ .fniv = gen_vabsdu,
+ .fno = gen_helper_VABSDUW,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ };
+
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &op[vece]);
+
+ return true;
+}
+
+TRANS_FLAGS2(ISA300, VABSDUB, do_vabsdu, MO_8)
+TRANS_FLAGS2(ISA300, VABSDUH, do_vabsdu, MO_16)
+TRANS_FLAGS2(ISA300, VABSDUW, do_vabsdu, MO_32)
+
+static bool do_vdiv_vmod(DisasContext *ctx, arg_VX *a, const int vece,
+ void (*func_32)(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b),
+ void (*func_64)(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b))
+{
+ const GVecGen3 op = {
+ .fni4 = func_32,
+ .fni8 = func_64,
+ .vece = vece
+ };
+
+ REQUIRE_VECTOR(ctx);
+
+ tcg_gen_gvec_3(avr_full_offset(a->vrt), avr_full_offset(a->vra),
+ avr_full_offset(a->vrb), 16, 16, &op);
+
+ return true;
+}
+
+#define DIVU32(NAME, DIV) \
+static void NAME(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b) \
+{ \
+ TCGv_i32 zero = tcg_constant_i32(0); \
+ TCGv_i32 one = tcg_constant_i32(1); \
+ tcg_gen_movcond_i32(TCG_COND_EQ, b, b, zero, one, b); \
+ DIV(t, a, b); \
+}
+
+#define DIVS32(NAME, DIV) \
+static void NAME(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b) \
+{ \
+ TCGv_i32 t0 = tcg_temp_new_i32(); \
+ TCGv_i32 t1 = tcg_temp_new_i32(); \
+ tcg_gen_setcondi_i32(TCG_COND_EQ, t0, a, INT32_MIN); \
+ tcg_gen_setcondi_i32(TCG_COND_EQ, t1, b, -1); \
+ tcg_gen_and_i32(t0, t0, t1); \
+ tcg_gen_setcondi_i32(TCG_COND_EQ, t1, b, 0); \
+ tcg_gen_or_i32(t0, t0, t1); \
+ tcg_gen_movi_i32(t1, 0); \
+ tcg_gen_movcond_i32(TCG_COND_NE, b, t0, t1, t0, b); \
+ DIV(t, a, b); \
+}
+
+#define DIVU64(NAME, DIV) \
+static void NAME(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b) \
+{ \
+ TCGv_i64 zero = tcg_constant_i64(0); \
+ TCGv_i64 one = tcg_constant_i64(1); \
+ tcg_gen_movcond_i64(TCG_COND_EQ, b, b, zero, one, b); \
+ DIV(t, a, b); \
+}
+
+#define DIVS64(NAME, DIV) \
+static void NAME(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b) \
+{ \
+ TCGv_i64 t0 = tcg_temp_new_i64(); \
+ TCGv_i64 t1 = tcg_temp_new_i64(); \
+ tcg_gen_setcondi_i64(TCG_COND_EQ, t0, a, INT64_MIN); \
+ tcg_gen_setcondi_i64(TCG_COND_EQ, t1, b, -1); \
+ tcg_gen_and_i64(t0, t0, t1); \
+ tcg_gen_setcondi_i64(TCG_COND_EQ, t1, b, 0); \
+ tcg_gen_or_i64(t0, t0, t1); \
+ tcg_gen_movi_i64(t1, 0); \
+ tcg_gen_movcond_i64(TCG_COND_NE, b, t0, t1, t0, b); \
+ DIV(t, a, b); \
+}
+
+DIVS32(do_divsw, tcg_gen_div_i32)
+DIVU32(do_divuw, tcg_gen_divu_i32)
+DIVS64(do_divsd, tcg_gen_div_i64)
+DIVU64(do_divud, tcg_gen_divu_i64)
+
+TRANS_FLAGS2(ISA310, VDIVSW, do_vdiv_vmod, MO_32, do_divsw, NULL)
+TRANS_FLAGS2(ISA310, VDIVUW, do_vdiv_vmod, MO_32, do_divuw, NULL)
+TRANS_FLAGS2(ISA310, VDIVSD, do_vdiv_vmod, MO_64, NULL, do_divsd)
+TRANS_FLAGS2(ISA310, VDIVUD, do_vdiv_vmod, MO_64, NULL, do_divud)
+TRANS_FLAGS2(ISA310, VDIVSQ, do_vx_helper, gen_helper_VDIVSQ)
+TRANS_FLAGS2(ISA310, VDIVUQ, do_vx_helper, gen_helper_VDIVUQ)
+
+static void do_dives_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i64 val1, val2;
+
+ val1 = tcg_temp_new_i64();
+ val2 = tcg_temp_new_i64();
+
+ tcg_gen_ext_i32_i64(val1, a);
+ tcg_gen_ext_i32_i64(val2, b);
+
+ /* (a << 32)/b */
+ tcg_gen_shli_i64(val1, val1, 32);
+ tcg_gen_div_i64(val1, val1, val2);
+
+ /* if quotient doesn't fit in 32 bits the result is undefined */
+ tcg_gen_extrl_i64_i32(t, val1);
+}
+
+static void do_diveu_i32(TCGv_i32 t, TCGv_i32 a, TCGv_i32 b)
+{
+ TCGv_i64 val1, val2;
+
+ val1 = tcg_temp_new_i64();
+ val2 = tcg_temp_new_i64();
+
+ tcg_gen_extu_i32_i64(val1, a);
+ tcg_gen_extu_i32_i64(val2, b);
+
+ /* (a << 32)/b */
+ tcg_gen_shli_i64(val1, val1, 32);
+ tcg_gen_divu_i64(val1, val1, val2);
+
+ /* if quotient doesn't fit in 32 bits the result is undefined */
+ tcg_gen_extrl_i64_i32(t, val1);
+}
+
+DIVS32(do_divesw, do_dives_i32)
+DIVU32(do_diveuw, do_diveu_i32)
+
+DIVS32(do_modsw, tcg_gen_rem_i32)
+DIVU32(do_moduw, tcg_gen_remu_i32)
+DIVS64(do_modsd, tcg_gen_rem_i64)
+DIVU64(do_modud, tcg_gen_remu_i64)
+
+TRANS_FLAGS2(ISA310, VDIVESW, do_vdiv_vmod, MO_32, do_divesw, NULL)
+TRANS_FLAGS2(ISA310, VDIVEUW, do_vdiv_vmod, MO_32, do_diveuw, NULL)
+TRANS_FLAGS2(ISA310, VDIVESD, do_vx_helper, gen_helper_VDIVESD)
+TRANS_FLAGS2(ISA310, VDIVEUD, do_vx_helper, gen_helper_VDIVEUD)
+TRANS_FLAGS2(ISA310, VDIVESQ, do_vx_helper, gen_helper_VDIVESQ)
+TRANS_FLAGS2(ISA310, VDIVEUQ, do_vx_helper, gen_helper_VDIVEUQ)
+
+TRANS_FLAGS2(ISA310, VMODSW, do_vdiv_vmod, MO_32, do_modsw , NULL)
+TRANS_FLAGS2(ISA310, VMODUW, do_vdiv_vmod, MO_32, do_moduw, NULL)
+TRANS_FLAGS2(ISA310, VMODSD, do_vdiv_vmod, MO_64, NULL, do_modsd)
+TRANS_FLAGS2(ISA310, VMODUD, do_vdiv_vmod, MO_64, NULL, do_modud)
+TRANS_FLAGS2(ISA310, VMODSQ, do_vx_helper, gen_helper_VMODSQ)
+TRANS_FLAGS2(ISA310, VMODUQ, do_vx_helper, gen_helper_VMODUQ)
+
+#undef DIVS32
+#undef DIVU32
+#undef DIVS64
+#undef DIVU64
+
#undef GEN_VR_LDX
#undef GEN_VR_STX
#undef GEN_VR_LVE
diff --git a/target/ppc/translate/vmx-ops.c.inc b/target/ppc/translate/vmx-ops.c.inc
index f3f4855111..33fec8aca4 100644
--- a/target/ppc/translate/vmx-ops.c.inc
+++ b/target/ppc/translate/vmx-ops.c.inc
@@ -83,12 +83,6 @@ GEN_VXFORM(vminsb, 1, 12),
GEN_VXFORM(vminsh, 1, 13),
GEN_VXFORM(vminsw, 1, 14),
GEN_VXFORM_207(vminsd, 1, 15),
-GEN_VXFORM_DUAL(vavgub, vabsdub, 1, 16, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_DUAL(vavguh, vabsduh, 1, 17, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_DUAL(vavguw, vabsduw, 1, 18, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM(vavgsb, 1, 20),
-GEN_VXFORM(vavgsh, 1, 21),
-GEN_VXFORM(vavgsw, 1, 22),
GEN_VXFORM(vmrghb, 6, 0),
GEN_VXFORM(vmrghh, 6, 1),
GEN_VXFORM(vmrghw, 6, 2),
@@ -101,43 +95,13 @@ GEN_VXFORM_DUAL(vmrgow, vextuwlx, 6, 26, PPC_NONE, PPC2_ALTIVEC_207),
GEN_VXFORM_300(vextubrx, 6, 28),
GEN_VXFORM_300(vextuhrx, 6, 29),
GEN_VXFORM_DUAL(vmrgew, vextuwrx, 6, 30, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM(vmuloub, 4, 0),
-GEN_VXFORM(vmulouh, 4, 1),
-GEN_VXFORM_DUAL(vmulouw, vmuluwm, 4, 2, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM(vmulosb, 4, 4),
-GEN_VXFORM(vmulosh, 4, 5),
-GEN_VXFORM_207(vmulosw, 4, 6),
-GEN_VXFORM_310(vmulld, 4, 7),
-GEN_VXFORM(vmuleub, 4, 8),
-GEN_VXFORM(vmuleuh, 4, 9),
-GEN_VXFORM_DUAL(vmuleuw, vmulhuw, 4, 10, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_310(vmulhud, 4, 11),
-GEN_VXFORM(vmulesb, 4, 12),
-GEN_VXFORM(vmulesh, 4, 13),
-GEN_VXFORM_DUAL(vmulesw, vmulhsw, 4, 14, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_310(vmulhsd, 4, 15),
-GEN_VXFORM(vslb, 2, 4),
-GEN_VXFORM(vslh, 2, 5),
-GEN_VXFORM_DUAL(vslw, vrlwnm, 2, 6, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_207(vsld, 2, 23),
-GEN_VXFORM(vsrb, 2, 8),
-GEN_VXFORM(vsrh, 2, 9),
-GEN_VXFORM(vsrw, 2, 10),
-GEN_VXFORM_207(vsrd, 2, 27),
-GEN_VXFORM(vsrab, 2, 12),
-GEN_VXFORM(vsrah, 2, 13),
-GEN_VXFORM(vsraw, 2, 14),
-GEN_VXFORM_207(vsrad, 2, 15),
+GEN_VXFORM_207(vmuluwm, 4, 2),
GEN_VXFORM_300(vsrv, 2, 28),
GEN_VXFORM_300(vslv, 2, 29),
GEN_VXFORM(vslo, 6, 16),
GEN_VXFORM(vsro, 6, 17),
-GEN_VXFORM(vaddcuw, 0, 6),
-GEN_HANDLER_E_2(vprtybw, 0x4, 0x1, 0x18, 8, 0, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E_2(vprtybd, 0x4, 0x1, 0x18, 9, 0, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E_2(vprtybq, 0x4, 0x1, 0x18, 10, 0, PPC_NONE, PPC2_ISA300),
-GEN_VXFORM_DUAL(vsubcuw, xpnd04_1, 0, 22, PPC_ALTIVEC, PPC_NONE),
+GEN_VXFORM(xpnd04_1, 0, 22),
GEN_VXFORM_300(bcdsr, 0, 23),
GEN_VXFORM_300(bcdsr, 0, 31),
GEN_VXFORM_DUAL(vaddubs, vmul10uq, 0, 8, PPC_ALTIVEC, PPC_NONE),
@@ -152,17 +116,9 @@ GEN_VXFORM(vsubuws, 0, 26),
GEN_VXFORM_DUAL(vsubsbs, bcdtrunc, 0, 28, PPC_ALTIVEC, PPC2_ISA300),
GEN_VXFORM(vsubshs, 0, 29),
GEN_VXFORM_DUAL(vsubsws, xpnd04_2, 0, 30, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_207(vadduqm, 0, 4),
-GEN_VXFORM_207(vaddcuq, 0, 5),
-GEN_VXFORM_DUAL(vaddeuqm, vaddecuq, 30, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM_DUAL(vsubuqm, bcdtrunc, 0, 20, PPC2_ALTIVEC_207, PPC2_ISA300),
-GEN_VXFORM_DUAL(vsubcuq, bcdutrunc, 0, 21, PPC2_ALTIVEC_207, PPC2_ISA300),
-GEN_VXFORM_DUAL(vsubeuqm, vsubecuq, 31, 0xFF, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM(vrlb, 2, 0),
-GEN_VXFORM(vrlh, 2, 1),
-GEN_VXFORM_DUAL(vrlw, vrlwmi, 2, 2, PPC_ALTIVEC, PPC_NONE),
-GEN_VXFORM_DUAL(vrld, vrldmi, 2, 3, PPC_NONE, PPC2_ALTIVEC_207),
-GEN_VXFORM_DUAL(vsl, vrldnm, 2, 7, PPC_ALTIVEC, PPC_NONE),
+GEN_VXFORM_300(bcdtrunc, 0, 20),
+GEN_VXFORM_300(bcdutrunc, 0, 21),
+GEN_VXFORM(vsl, 2, 7),
GEN_VXFORM(vsr, 2, 11),
GEN_VXFORM(vpkuhum, 7, 0),
GEN_VXFORM(vpkuwum, 7, 1),
@@ -198,22 +154,10 @@ GEN_HANDLER2_E(name, str, 0x4, opc2, opc3, 0x00000000, PPC_NONE, PPC2_ISA300),
GEN_VXRFORM1_300(name, name, #name, opc2, opc3) \
GEN_VXRFORM1_300(name##_dot, name##_, #name ".", opc2, (opc3 | (0x1 << 4)))
-GEN_VXRFORM_300(vcmpnezb, 3, 4)
-GEN_VXRFORM_300(vcmpnezh, 3, 5)
-GEN_VXRFORM_300(vcmpnezw, 3, 6)
-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_DUAL(vcmpeqfp, vcmpequd, 3, 3, PPC_ALTIVEC, PPC_NONE)
+GEN_VXRFORM(vcmpeqfp, 3, 3)
GEN_VXRFORM(vcmpgefp, 3, 7)
-GEN_VXRFORM_DUAL(vcmpgtfp, vcmpgtud, 3, 11, PPC_ALTIVEC, PPC_NONE)
-GEN_VXRFORM_DUAL(vcmpbfp, vcmpgtsd, 3, 15, PPC_ALTIVEC, PPC_NONE)
-GEN_VXRFORM_DUAL(vcmpequb, vcmpneb, 3, 0, PPC_ALTIVEC, PPC_NONE)
-GEN_VXRFORM_DUAL(vcmpequh, vcmpneh, 3, 1, PPC_ALTIVEC, PPC_NONE)
-GEN_VXRFORM_DUAL(vcmpequw, vcmpnew, 3, 2, PPC_ALTIVEC, PPC_NONE)
+GEN_VXRFORM(vcmpgtfp, 3, 11)
+GEN_VXRFORM(vcmpbfp, 3, 15)
#define GEN_VXFORM_DUAL_INV(name0, name1, opc2, opc3, inval0, inval1, type) \
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, \
@@ -225,27 +169,15 @@ GEN_VXFORM_DUAL_INV(vsplth, vextractuh, 6, 9, 0x00000000, 0x100000,
GEN_VXFORM_DUAL_INV(vspltw, vextractuw, 6, 10, 0x00000000, 0x100000,
PPC_ALTIVEC),
GEN_VXFORM_300_EXT(vextractd, 6, 11, 0x100000),
-GEN_VXFORM_DUAL_INV(vspltisb, vinsertb, 6, 12, 0x00000000, 0x100000,
- PPC_ALTIVEC),
-GEN_VXFORM_DUAL_INV(vspltish, vinserth, 6, 13, 0x00000000, 0x100000,
- PPC_ALTIVEC),
-GEN_VXFORM_DUAL_INV(vspltisw, vinsertw, 6, 14, 0x00000000, 0x100000,
- PPC_ALTIVEC),
-GEN_VXFORM_300_EXT(vinsertd, 6, 15, 0x100000),
-GEN_VXFORM_300_EO(vnegw, 0x01, 0x18, 0x06),
-GEN_VXFORM_300_EO(vnegd, 0x01, 0x18, 0x07),
-GEN_VXFORM_300_EO(vextsb2w, 0x01, 0x18, 0x10),
-GEN_VXFORM_300_EO(vextsh2w, 0x01, 0x18, 0x11),
-GEN_VXFORM_300_EO(vextsb2d, 0x01, 0x18, 0x18),
-GEN_VXFORM_300_EO(vextsh2d, 0x01, 0x18, 0x19),
-GEN_VXFORM_300_EO(vextsw2d, 0x01, 0x18, 0x1A),
+GEN_VXFORM(vspltisb, 6, 12),
+GEN_VXFORM(vspltish, 6, 13),
+GEN_VXFORM(vspltisw, 6, 14),
GEN_VXFORM_300_EO(vctzb, 0x01, 0x18, 0x1C),
GEN_VXFORM_300_EO(vctzh, 0x01, 0x18, 0x1D),
GEN_VXFORM_300_EO(vctzw, 0x01, 0x18, 0x1E),
GEN_VXFORM_300_EO(vctzd, 0x01, 0x18, 0x1F),
GEN_VXFORM_300_EO(vclzlsbb, 0x01, 0x18, 0x0),
GEN_VXFORM_300_EO(vctzlsbb, 0x01, 0x18, 0x1),
-GEN_VXFORM_300(vpermr, 0x1D, 0xFF),
#define GEN_VXFORM_NOA(name, opc2, opc3) \
GEN_HANDLER(name, 0x04, opc2, opc3, 0x001f0000, PPC_ALTIVEC)
@@ -273,14 +205,8 @@ GEN_VXFORM_UIMM(vcfsx, 5, 13),
GEN_VXFORM_UIMM(vctuxs, 5, 14),
GEN_VXFORM_UIMM(vctsxs, 5, 15),
-
#define GEN_VAFORM_PAIRED(name0, name1, opc2) \
GEN_HANDLER(name0##_##name1, 0x04, opc2, 0xFF, 0x00000000, PPC_ALTIVEC)
-GEN_VAFORM_PAIRED(vmhaddshs, vmhraddshs, 16),
-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),
GEN_VXFORM_DUAL(vclzb, vpopcntb, 1, 28, PPC_NONE, PPC2_ALTIVEC_207),
@@ -294,7 +220,6 @@ GEN_VXFORM_207(vgbbd, 6, 20),
GEN_VXFORM_207(vpmsumb, 4, 16),
GEN_VXFORM_207(vpmsumh, 4, 17),
GEN_VXFORM_207(vpmsumw, 4, 18),
-GEN_VXFORM_207(vpmsumd, 4, 19),
GEN_VXFORM_207(vsbox, 4, 23),
diff --git a/target/ppc/translate/vsx-impl.c.inc b/target/ppc/translate/vsx-impl.c.inc
index 57a7f73bba..0266f09119 100644
--- a/target/ppc/translate/vsx-impl.c.inc
+++ b/target/ppc/translate/vsx-impl.c.inc
@@ -1,29 +1,26 @@
/*** VSX extension ***/
-static inline void get_cpu_vsrh(TCGv_i64 dst, int n)
+static inline void get_cpu_vsr(TCGv_i64 dst, int n, bool high)
{
- tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, true));
+ tcg_gen_ld_i64(dst, tcg_env, vsr64_offset(n, high));
}
-static inline void get_cpu_vsrl(TCGv_i64 dst, int n)
+static inline void set_cpu_vsr(int n, TCGv_i64 src, bool high)
{
- tcg_gen_ld_i64(dst, cpu_env, vsr64_offset(n, false));
+ tcg_gen_st_i64(src, tcg_env, vsr64_offset(n, high));
}
-static inline void set_cpu_vsrh(int n, TCGv_i64 src)
-{
- tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, true));
-}
-
-static inline void set_cpu_vsrl(int n, TCGv_i64 src)
+static inline TCGv_ptr gen_vsr_ptr(int reg)
{
- tcg_gen_st_i64(src, cpu_env, vsr64_offset(n, false));
+ TCGv_ptr r = tcg_temp_new_ptr();
+ tcg_gen_addi_ptr(r, tcg_env, vsr_full_offset(reg));
+ return r;
}
-static inline TCGv_ptr gen_vsr_ptr(int reg)
+static inline TCGv_ptr gen_acc_ptr(int reg)
{
TCGv_ptr r = tcg_temp_new_ptr();
- tcg_gen_addi_ptr(r, cpu_env, vsr_full_offset(reg));
+ tcg_gen_addi_ptr(r, tcg_env, acc_full_offset(reg));
return r;
}
@@ -41,10 +38,8 @@ static void gen_##name(DisasContext *ctx) \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
gen_qemu_##operation(ctx, t0, EA); \
- set_cpu_vsrh(xT(ctx->opcode), t0); \
+ set_cpu_vsr(xT(ctx->opcode), t0, true); \
/* NOTE: cpu_vsrl is undefined */ \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
}
VSX_LOAD_SCALAR(lxsdx, ld64_i64)
@@ -67,12 +62,10 @@ static void gen_lxvd2x(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
gen_qemu_ld64_i64(ctx, t0, EA);
- set_cpu_vsrh(xT(ctx->opcode), t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, true);
tcg_gen_addi_tl(EA, EA, 8);
gen_qemu_ld64_i64(ctx, t0, EA);
- set_cpu_vsrl(xT(ctx->opcode), t0);
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, false);
}
static void gen_lxvw4x(DisasContext *ctx)
@@ -95,25 +88,20 @@ static void gen_lxvw4x(DisasContext *ctx)
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_shri_i64(t1, t0, 32);
tcg_gen_deposit_i64(xth, t1, t0, 32, 32);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_qemu_ld_i64(t0, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_shri_i64(t1, t0, 32);
tcg_gen_deposit_i64(xtl, t1, t0, 32, 32);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
} else {
- tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
}
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
- tcg_temp_free(EA);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_lxvwsx(DisasContext *ctx)
@@ -141,9 +129,6 @@ static void gen_lxvwsx(DisasContext *ctx)
data = tcg_temp_new_i32();
tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
-
- tcg_temp_free(EA);
- tcg_temp_free_i32(data);
}
static void gen_lxvdsx(DisasContext *ctx)
@@ -162,17 +147,14 @@ static void gen_lxvdsx(DisasContext *ctx)
gen_addr_reg_index(ctx, EA);
data = tcg_temp_new_i64();
- tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
- tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
-
- tcg_temp_free(EA);
- tcg_temp_free_i64(data);
+ tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ));
+ tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
}
static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
TCGv_i64 inh, TCGv_i64 inl)
{
- TCGv_i64 mask = tcg_const_i64(0x00FF00FF00FF00FF);
+ TCGv_i64 mask = tcg_constant_i64(0x00FF00FF00FF00FF);
TCGv_i64 t0 = tcg_temp_new_i64();
TCGv_i64 t1 = tcg_temp_new_i64();
@@ -189,10 +171,6 @@ static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
tcg_gen_shri_i64(t1, inl, 8);
tcg_gen_and_i64(t1, t1, mask);
tcg_gen_or_i64(outl, t0, t1);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(mask);
}
static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
@@ -207,10 +185,8 @@ static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
tcg_gen_deposit_i64(outh, outh, hi, 32, 32);
tcg_gen_shri_i64(outl, lo, 32);
tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
-
- tcg_temp_free_i64(hi);
- tcg_temp_free_i64(lo);
}
+
static void gen_lxvh8x(DisasContext *ctx)
{
TCGv EA;
@@ -227,17 +203,14 @@ static void gen_lxvh8x(DisasContext *ctx)
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
if (ctx->le_mode) {
gen_bswap16x8(xth, xtl, xth, xtl);
}
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
- tcg_temp_free(EA);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_lxvb16x(DisasContext *ctx)
@@ -255,123 +228,12 @@ static void gen_lxvb16x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEQ);
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
- tcg_temp_free(EA);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
-}
-
-#define VSX_VECTOR_LOAD(name, op, indexed) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- int xt; \
- TCGv EA; \
- TCGv_i64 xth; \
- TCGv_i64 xtl; \
- \
- if (indexed) { \
- xt = xT(ctx->opcode); \
- } else { \
- xt = DQxT(ctx->opcode); \
- } \
- \
- if (xt < 32) { \
- if (unlikely(!ctx->vsx_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
- return; \
- } \
- } else { \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- } \
- xth = tcg_temp_new_i64(); \
- xtl = tcg_temp_new_i64(); \
- gen_set_access_type(ctx, ACCESS_INT); \
- EA = tcg_temp_new(); \
- if (indexed) { \
- gen_addr_reg_index(ctx, EA); \
- } else { \
- gen_addr_imm_index(ctx, EA, 0x0F); \
- } \
- if (ctx->le_mode) { \
- tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ); \
- set_cpu_vsrl(xt, xtl); \
- tcg_gen_addi_tl(EA, EA, 8); \
- tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ); \
- set_cpu_vsrh(xt, xth); \
- } else { \
- tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ); \
- set_cpu_vsrh(xt, xth); \
- tcg_gen_addi_tl(EA, EA, 8); \
- tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ); \
- set_cpu_vsrl(xt, xtl); \
- } \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(xth); \
- tcg_temp_free_i64(xtl); \
-}
-
-VSX_VECTOR_LOAD(lxv, ld_i64, 0)
-VSX_VECTOR_LOAD(lxvx, ld_i64, 1)
-
-#define VSX_VECTOR_STORE(name, op, indexed) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- int xt; \
- TCGv EA; \
- TCGv_i64 xth; \
- TCGv_i64 xtl; \
- \
- if (indexed) { \
- xt = xT(ctx->opcode); \
- } else { \
- xt = DQxT(ctx->opcode); \
- } \
- \
- if (xt < 32) { \
- if (unlikely(!ctx->vsx_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
- return; \
- } \
- } else { \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- } \
- xth = tcg_temp_new_i64(); \
- xtl = tcg_temp_new_i64(); \
- get_cpu_vsrh(xth, xt); \
- get_cpu_vsrl(xtl, xt); \
- gen_set_access_type(ctx, ACCESS_INT); \
- EA = tcg_temp_new(); \
- if (indexed) { \
- gen_addr_reg_index(ctx, EA); \
- } else { \
- gen_addr_imm_index(ctx, EA, 0x0F); \
- } \
- if (ctx->le_mode) { \
- tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_LEQ); \
- tcg_gen_addi_tl(EA, EA, 8); \
- tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_LEQ); \
- } else { \
- tcg_gen_qemu_##op(xth, EA, ctx->mem_idx, MO_BEQ); \
- tcg_gen_addi_tl(EA, EA, 8); \
- tcg_gen_qemu_##op(xtl, EA, ctx->mem_idx, MO_BEQ); \
- } \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(xth); \
- tcg_temp_free_i64(xtl); \
-}
-
-VSX_VECTOR_STORE(stxv, st_i64, 0)
-VSX_VECTOR_STORE(stxvx, st_i64, 1)
+ tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
+}
#ifdef TARGET_PPC64
#define VSX_VECTOR_LOAD_STORE_LENGTH(name) \
@@ -395,9 +257,7 @@ static void gen_##name(DisasContext *ctx) \
xt = gen_vsr_ptr(xT(ctx->opcode)); \
gen_set_access_type(ctx, ACCESS_INT); \
gen_addr_register(ctx, EA); \
- gen_helper_##name(cpu_env, EA, xt, cpu_gpr[rB(ctx->opcode)]); \
- tcg_temp_free(EA); \
- tcg_temp_free_ptr(xt); \
+ gen_helper_##name(tcg_env, EA, xt, cpu_gpr[rB(ctx->opcode)]); \
}
VSX_VECTOR_LOAD_STORE_LENGTH(lxvl)
@@ -406,30 +266,6 @@ VSX_VECTOR_LOAD_STORE_LENGTH(stxvl)
VSX_VECTOR_LOAD_STORE_LENGTH(stxvll)
#endif
-#define VSX_LOAD_SCALAR_DS(name, operation) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 xth; \
- \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- xth = tcg_temp_new_i64(); \
- gen_set_access_type(ctx, ACCESS_INT); \
- EA = tcg_temp_new(); \
- gen_addr_imm_index(ctx, EA, 0x03); \
- gen_qemu_##operation(ctx, xth, EA); \
- set_cpu_vsrh(rD(ctx->opcode) + 32, xth); \
- /* NOTE: cpu_vsrl is undefined */ \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(xth); \
-}
-
-VSX_LOAD_SCALAR_DS(lxsd, ld64_i64)
-VSX_LOAD_SCALAR_DS(lxssp, ld32fs)
-
#define VSX_STORE_SCALAR(name, operation) \
static void gen_##name(DisasContext *ctx) \
{ \
@@ -443,10 +279,8 @@ static void gen_##name(DisasContext *ctx) \
gen_set_access_type(ctx, ACCESS_INT); \
EA = tcg_temp_new(); \
gen_addr_reg_index(ctx, EA); \
- get_cpu_vsrh(t0, xS(ctx->opcode)); \
+ get_cpu_vsr(t0, xS(ctx->opcode), true); \
gen_qemu_##operation(ctx, t0, EA); \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(t0); \
}
VSX_STORE_SCALAR(stxsdx, st64_i64)
@@ -468,13 +302,11 @@ static void gen_stxvd2x(DisasContext *ctx)
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- get_cpu_vsrh(t0, xS(ctx->opcode));
+ get_cpu_vsr(t0, xS(ctx->opcode), true);
gen_qemu_st64_i64(ctx, t0, EA);
tcg_gen_addi_tl(EA, EA, 8);
- get_cpu_vsrl(t0, xS(ctx->opcode));
+ get_cpu_vsr(t0, xS(ctx->opcode), false);
gen_qemu_st64_i64(ctx, t0, EA);
- tcg_temp_free(EA);
- tcg_temp_free_i64(t0);
}
static void gen_stxvw4x(DisasContext *ctx)
@@ -489,8 +321,8 @@ static void gen_stxvw4x(DisasContext *ctx)
}
xsh = tcg_temp_new_i64();
xsl = tcg_temp_new_i64();
- get_cpu_vsrh(xsh, xS(ctx->opcode));
- get_cpu_vsrl(xsl, xS(ctx->opcode));
+ get_cpu_vsr(xsh, xS(ctx->opcode), true);
+ get_cpu_vsr(xsl, xS(ctx->opcode), false);
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
@@ -500,21 +332,16 @@ static void gen_stxvw4x(DisasContext *ctx)
tcg_gen_shri_i64(t0, xsh, 32);
tcg_gen_deposit_i64(t1, t0, xsh, 32, 32);
- tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
+ tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
tcg_gen_addi_tl(EA, EA, 8);
tcg_gen_shri_i64(t0, xsl, 32);
tcg_gen_deposit_i64(t1, t0, xsl, 32, 32);
- tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEQ);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
+ tcg_gen_qemu_st_i64(t1, EA, ctx->mem_idx, MO_LEUQ);
} else {
- tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(xsh);
- tcg_temp_free_i64(xsl);
}
static void gen_stxvh8x(DisasContext *ctx)
@@ -529,8 +356,8 @@ static void gen_stxvh8x(DisasContext *ctx)
}
xsh = tcg_temp_new_i64();
xsl = tcg_temp_new_i64();
- get_cpu_vsrh(xsh, xS(ctx->opcode));
- get_cpu_vsrl(xsl, xS(ctx->opcode));
+ get_cpu_vsr(xsh, xS(ctx->opcode), true);
+ get_cpu_vsr(xsl, xS(ctx->opcode), false);
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
@@ -539,19 +366,14 @@ static void gen_stxvh8x(DisasContext *ctx)
TCGv_i64 outl = tcg_temp_new_i64();
gen_bswap16x8(outh, outl, xsh, xsl);
- tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(outh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEQ);
- tcg_temp_free_i64(outh);
- tcg_temp_free_i64(outl);
+ tcg_gen_qemu_st_i64(outl, EA, ctx->mem_idx, MO_BEUQ);
} else {
- tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
}
- tcg_temp_free(EA);
- tcg_temp_free_i64(xsh);
- tcg_temp_free_i64(xsl);
}
static void gen_stxvb16x(DisasContext *ctx)
@@ -566,43 +388,16 @@ static void gen_stxvb16x(DisasContext *ctx)
}
xsh = tcg_temp_new_i64();
xsl = tcg_temp_new_i64();
- get_cpu_vsrh(xsh, xS(ctx->opcode));
- get_cpu_vsrl(xsl, xS(ctx->opcode));
+ get_cpu_vsr(xsh, xS(ctx->opcode), true);
+ get_cpu_vsr(xsl, xS(ctx->opcode), false);
gen_set_access_type(ctx, ACCESS_INT);
EA = tcg_temp_new();
gen_addr_reg_index(ctx, EA);
- tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEQ);
+ tcg_gen_qemu_st_i64(xsh, EA, ctx->mem_idx, MO_BEUQ);
tcg_gen_addi_tl(EA, EA, 8);
- tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEQ);
- tcg_temp_free(EA);
- tcg_temp_free_i64(xsh);
- tcg_temp_free_i64(xsl);
+ tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
}
-#define VSX_STORE_SCALAR_DS(name, operation) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv EA; \
- TCGv_i64 xth; \
- \
- if (unlikely(!ctx->altivec_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VPU); \
- return; \
- } \
- xth = tcg_temp_new_i64(); \
- get_cpu_vsrh(xth, rD(ctx->opcode) + 32); \
- gen_set_access_type(ctx, ACCESS_INT); \
- EA = tcg_temp_new(); \
- gen_addr_imm_index(ctx, EA, 0x03); \
- gen_qemu_##operation(ctx, xth, EA); \
- /* NOTE: cpu_vsrl is undefined */ \
- tcg_temp_free(EA); \
- tcg_temp_free_i64(xth); \
-}
-
-VSX_STORE_SCALAR_DS(stxsd, st64_i64)
-VSX_STORE_SCALAR_DS(stxssp, st32fs)
-
static void gen_mfvsrwz(DisasContext *ctx)
{
if (xS(ctx->opcode) < 32) {
@@ -618,11 +413,9 @@ static void gen_mfvsrwz(DisasContext *ctx)
}
TCGv_i64 tmp = tcg_temp_new_i64();
TCGv_i64 xsh = tcg_temp_new_i64();
- get_cpu_vsrh(xsh, xS(ctx->opcode));
+ get_cpu_vsr(xsh, xS(ctx->opcode), true);
tcg_gen_ext32u_i64(tmp, xsh);
tcg_gen_trunc_i64_tl(cpu_gpr[rA(ctx->opcode)], tmp);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(xsh);
}
static void gen_mtvsrwa(DisasContext *ctx)
@@ -642,9 +435,7 @@ static void gen_mtvsrwa(DisasContext *ctx)
TCGv_i64 xsh = tcg_temp_new_i64();
tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
tcg_gen_ext32s_i64(xsh, tmp);
- set_cpu_vsrh(xT(ctx->opcode), xsh);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(xsh);
+ set_cpu_vsr(xT(ctx->opcode), xsh, true);
}
static void gen_mtvsrwz(DisasContext *ctx)
@@ -664,9 +455,7 @@ static void gen_mtvsrwz(DisasContext *ctx)
TCGv_i64 xsh = tcg_temp_new_i64();
tcg_gen_extu_tl_i64(tmp, cpu_gpr[rA(ctx->opcode)]);
tcg_gen_ext32u_i64(xsh, tmp);
- set_cpu_vsrh(xT(ctx->opcode), xsh);
- tcg_temp_free_i64(tmp);
- tcg_temp_free_i64(xsh);
+ set_cpu_vsr(xT(ctx->opcode), xsh, true);
}
#if defined(TARGET_PPC64)
@@ -685,9 +474,8 @@ static void gen_mfvsrd(DisasContext *ctx)
}
}
t0 = tcg_temp_new_i64();
- get_cpu_vsrh(t0, xS(ctx->opcode));
+ get_cpu_vsr(t0, xS(ctx->opcode), true);
tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
- tcg_temp_free_i64(t0);
}
static void gen_mtvsrd(DisasContext *ctx)
@@ -706,8 +494,7 @@ static void gen_mtvsrd(DisasContext *ctx)
}
t0 = tcg_temp_new_i64();
tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
- set_cpu_vsrh(xT(ctx->opcode), t0);
- tcg_temp_free_i64(t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, true);
}
static void gen_mfvsrld(DisasContext *ctx)
@@ -725,9 +512,8 @@ static void gen_mfvsrld(DisasContext *ctx)
}
}
t0 = tcg_temp_new_i64();
- get_cpu_vsrl(t0, xS(ctx->opcode));
+ get_cpu_vsr(t0, xS(ctx->opcode), false);
tcg_gen_mov_i64(cpu_gpr[rA(ctx->opcode)], t0);
- tcg_temp_free_i64(t0);
}
static void gen_mtvsrdd(DisasContext *ctx)
@@ -751,11 +537,10 @@ static void gen_mtvsrdd(DisasContext *ctx)
} else {
tcg_gen_mov_i64(t0, cpu_gpr[rA(ctx->opcode)]);
}
- set_cpu_vsrh(xT(ctx->opcode), t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, true);
tcg_gen_mov_i64(t0, cpu_gpr[rB(ctx->opcode)]);
- set_cpu_vsrl(xT(ctx->opcode), t0);
- tcg_temp_free_i64(t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, false);
}
static void gen_mtvsrws(DisasContext *ctx)
@@ -776,66 +561,22 @@ static void gen_mtvsrws(DisasContext *ctx)
t0 = tcg_temp_new_i64();
tcg_gen_deposit_i64(t0, cpu_gpr[rA(ctx->opcode)],
cpu_gpr[rA(ctx->opcode)], 32, 32);
- set_cpu_vsrl(xT(ctx->opcode), t0);
- set_cpu_vsrh(xT(ctx->opcode), t0);
- tcg_temp_free_i64(t0);
+ set_cpu_vsr(xT(ctx->opcode), t0, false);
+ set_cpu_vsr(xT(ctx->opcode), t0, true);
}
#endif
-static void gen_xxpermdi(DisasContext *ctx)
-{
- TCGv_i64 xh, xl;
-
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
-
- xh = tcg_temp_new_i64();
- xl = tcg_temp_new_i64();
-
- if (unlikely((xT(ctx->opcode) == xA(ctx->opcode)) ||
- (xT(ctx->opcode) == xB(ctx->opcode)))) {
- if ((DM(ctx->opcode) & 2) == 0) {
- get_cpu_vsrh(xh, xA(ctx->opcode));
- } else {
- get_cpu_vsrl(xh, xA(ctx->opcode));
- }
- if ((DM(ctx->opcode) & 1) == 0) {
- get_cpu_vsrh(xl, xB(ctx->opcode));
- } else {
- get_cpu_vsrl(xl, xB(ctx->opcode));
- }
-
- set_cpu_vsrh(xT(ctx->opcode), xh);
- set_cpu_vsrl(xT(ctx->opcode), xl);
- } else {
- if ((DM(ctx->opcode) & 2) == 0) {
- get_cpu_vsrh(xh, xA(ctx->opcode));
- set_cpu_vsrh(xT(ctx->opcode), xh);
- } else {
- get_cpu_vsrl(xh, xA(ctx->opcode));
- set_cpu_vsrh(xT(ctx->opcode), xh);
- }
- if ((DM(ctx->opcode) & 1) == 0) {
- get_cpu_vsrh(xl, xB(ctx->opcode));
- set_cpu_vsrl(xT(ctx->opcode), xl);
- } else {
- get_cpu_vsrl(xl, xB(ctx->opcode));
- set_cpu_vsrl(xT(ctx->opcode), xl);
- }
- }
- tcg_temp_free_i64(xh);
- tcg_temp_free_i64(xl);
-}
-
#define OP_ABS 1
#define OP_NABS 2
#define OP_NEG 3
#define OP_CPSGN 4
#define SGN_MASK_DP 0x8000000000000000ull
#define SGN_MASK_SP 0x8000000080000000ull
+#define EXP_MASK_DP 0x7FF0000000000000ull
+#define EXP_MASK_SP 0x7F8000007F800000ull
+#define FRC_MASK_DP (~(SGN_MASK_DP | EXP_MASK_DP))
+#define FRC_MASK_SP (~(SGN_MASK_SP | EXP_MASK_SP))
#define VSX_SCALAR_MOVE(name, op, sgn_mask) \
static void glue(gen_, name)(DisasContext *ctx) \
@@ -847,7 +588,7 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
xb = tcg_temp_new_i64(); \
sgm = tcg_temp_new_i64(); \
- get_cpu_vsrh(xb, xB(ctx->opcode)); \
+ get_cpu_vsr(xb, xB(ctx->opcode), true); \
tcg_gen_movi_i64(sgm, sgn_mask); \
switch (op) { \
case OP_ABS: { \
@@ -864,17 +605,15 @@ static void glue(gen_, name)(DisasContext *ctx) \
} \
case OP_CPSGN: { \
TCGv_i64 xa = tcg_temp_new_i64(); \
- get_cpu_vsrh(xa, xA(ctx->opcode)); \
+ get_cpu_vsr(xa, xA(ctx->opcode), true); \
tcg_gen_and_i64(xa, xa, sgm); \
tcg_gen_andc_i64(xb, xb, sgm); \
tcg_gen_or_i64(xb, xb, xa); \
- tcg_temp_free_i64(xa); \
break; \
} \
} \
- set_cpu_vsrh(xT(ctx->opcode), xb); \
- tcg_temp_free_i64(xb); \
- tcg_temp_free_i64(sgm); \
+ set_cpu_vsr(xT(ctx->opcode), xb, true); \
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
}
VSX_SCALAR_MOVE(xsabsdp, OP_ABS, SGN_MASK_DP)
@@ -898,8 +637,8 @@ static void glue(gen_, name)(DisasContext *ctx) \
xbl = tcg_temp_new_i64(); \
sgm = tcg_temp_new_i64(); \
tmp = tcg_temp_new_i64(); \
- get_cpu_vsrh(xbh, xb); \
- get_cpu_vsrl(xbl, xb); \
+ get_cpu_vsr(xbh, xb, true); \
+ get_cpu_vsr(xbl, xb, false); \
tcg_gen_movi_i64(sgm, sgn_mask); \
switch (op) { \
case OP_ABS: \
@@ -914,19 +653,14 @@ static void glue(gen_, name)(DisasContext *ctx) \
case OP_CPSGN: \
xah = tcg_temp_new_i64(); \
xa = rA(ctx->opcode) + 32; \
- get_cpu_vsrh(tmp, xa); \
+ get_cpu_vsr(tmp, xa, true); \
tcg_gen_and_i64(xah, tmp, sgm); \
tcg_gen_andc_i64(xbh, xbh, sgm); \
tcg_gen_or_i64(xbh, xbh, xah); \
- tcg_temp_free_i64(xah); \
break; \
} \
- set_cpu_vsrh(xt, xbh); \
- set_cpu_vsrl(xt, xbl); \
- tcg_temp_free_i64(xbl); \
- tcg_temp_free_i64(xbh); \
- tcg_temp_free_i64(sgm); \
- tcg_temp_free_i64(tmp); \
+ set_cpu_vsr(xt, xbh, true); \
+ set_cpu_vsr(xt, xbl, false); \
}
VSX_SCALAR_MOVE_QP(xsabsqp, OP_ABS, SGN_MASK_DP)
@@ -934,67 +668,125 @@ VSX_SCALAR_MOVE_QP(xsnabsqp, OP_NABS, SGN_MASK_DP)
VSX_SCALAR_MOVE_QP(xsnegqp, OP_NEG, SGN_MASK_DP)
VSX_SCALAR_MOVE_QP(xscpsgnqp, OP_CPSGN, SGN_MASK_DP)
-#define VSX_VECTOR_MOVE(name, op, sgn_mask) \
-static void glue(gen_, name)(DisasContext *ctx) \
- { \
- TCGv_i64 xbh, xbl, sgm; \
- if (unlikely(!ctx->vsx_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
- return; \
- } \
- xbh = tcg_temp_new_i64(); \
- xbl = tcg_temp_new_i64(); \
- sgm = tcg_temp_new_i64(); \
- get_cpu_vsrh(xbh, xB(ctx->opcode)); \
- get_cpu_vsrl(xbl, xB(ctx->opcode)); \
- tcg_gen_movi_i64(sgm, sgn_mask); \
- switch (op) { \
- case OP_ABS: { \
- tcg_gen_andc_i64(xbh, xbh, sgm); \
- tcg_gen_andc_i64(xbl, xbl, sgm); \
- break; \
- } \
- case OP_NABS: { \
- tcg_gen_or_i64(xbh, xbh, sgm); \
- tcg_gen_or_i64(xbl, xbl, sgm); \
- break; \
- } \
- case OP_NEG: { \
- tcg_gen_xor_i64(xbh, xbh, sgm); \
- tcg_gen_xor_i64(xbl, xbl, sgm); \
- break; \
- } \
- case OP_CPSGN: { \
- TCGv_i64 xah = tcg_temp_new_i64(); \
- TCGv_i64 xal = tcg_temp_new_i64(); \
- get_cpu_vsrh(xah, xA(ctx->opcode)); \
- get_cpu_vsrl(xal, xA(ctx->opcode)); \
- tcg_gen_and_i64(xah, xah, sgm); \
- tcg_gen_and_i64(xal, xal, sgm); \
- tcg_gen_andc_i64(xbh, xbh, sgm); \
- tcg_gen_andc_i64(xbl, xbl, sgm); \
- tcg_gen_or_i64(xbh, xbh, xah); \
- tcg_gen_or_i64(xbl, xbl, xal); \
- tcg_temp_free_i64(xah); \
- tcg_temp_free_i64(xal); \
- break; \
- } \
- } \
- set_cpu_vsrh(xT(ctx->opcode), xbh); \
- set_cpu_vsrl(xT(ctx->opcode), xbl); \
- tcg_temp_free_i64(xbh); \
- tcg_temp_free_i64(xbl); \
- tcg_temp_free_i64(sgm); \
- }
-
-VSX_VECTOR_MOVE(xvabsdp, OP_ABS, SGN_MASK_DP)
-VSX_VECTOR_MOVE(xvnabsdp, OP_NABS, SGN_MASK_DP)
-VSX_VECTOR_MOVE(xvnegdp, OP_NEG, SGN_MASK_DP)
-VSX_VECTOR_MOVE(xvcpsgndp, OP_CPSGN, SGN_MASK_DP)
-VSX_VECTOR_MOVE(xvabssp, OP_ABS, SGN_MASK_SP)
-VSX_VECTOR_MOVE(xvnabssp, OP_NABS, SGN_MASK_SP)
-VSX_VECTOR_MOVE(xvnegsp, OP_NEG, SGN_MASK_SP)
-VSX_VECTOR_MOVE(xvcpsgnsp, OP_CPSGN, SGN_MASK_SP)
+#define TCG_OP_IMM_i64(FUNC, OP, IMM) \
+ static void FUNC(TCGv_i64 t, TCGv_i64 b) \
+ { \
+ OP(t, b, IMM); \
+ }
+
+TCG_OP_IMM_i64(do_xvabssp_i64, tcg_gen_andi_i64, ~SGN_MASK_SP)
+TCG_OP_IMM_i64(do_xvnabssp_i64, tcg_gen_ori_i64, SGN_MASK_SP)
+TCG_OP_IMM_i64(do_xvnegsp_i64, tcg_gen_xori_i64, SGN_MASK_SP)
+TCG_OP_IMM_i64(do_xvabsdp_i64, tcg_gen_andi_i64, ~SGN_MASK_DP)
+TCG_OP_IMM_i64(do_xvnabsdp_i64, tcg_gen_ori_i64, SGN_MASK_DP)
+TCG_OP_IMM_i64(do_xvnegdp_i64, tcg_gen_xori_i64, SGN_MASK_DP)
+#undef TCG_OP_IMM_i64
+
+static void xv_msb_op1(unsigned vece, TCGv_vec t, TCGv_vec b,
+ void (*tcg_gen_op_vec)(unsigned, TCGv_vec, TCGv_vec, TCGv_vec))
+{
+ uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_op_vec(vece, t, b, tcg_constant_vec_matching(t, vece, msb));
+}
+
+static void do_xvabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ xv_msb_op1(vece, t, b, tcg_gen_andc_vec);
+}
+
+static void do_xvnabs_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ xv_msb_op1(vece, t, b, tcg_gen_or_vec);
+}
+
+static void do_xvneg_vec(unsigned vece, TCGv_vec t, TCGv_vec b)
+{
+ xv_msb_op1(vece, t, b, tcg_gen_xor_vec);
+}
+
+static bool do_vsx_msb_op(DisasContext *ctx, arg_XX2 *a, unsigned vece,
+ void (*vec)(unsigned, TCGv_vec, TCGv_vec),
+ void (*i64)(TCGv_i64, TCGv_i64))
+{
+ static const TCGOpcode vecop_list[] = {
+ 0
+ };
+
+ const GVecGen2 op = {
+ .fni8 = i64,
+ .fniv = vec,
+ .opt_opc = vecop_list,
+ .vece = vece
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_2(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
+ 16, 16, &op);
+
+ return true;
+}
+
+TRANS(XVABSDP, do_vsx_msb_op, MO_64, do_xvabs_vec, do_xvabsdp_i64)
+TRANS(XVNABSDP, do_vsx_msb_op, MO_64, do_xvnabs_vec, do_xvnabsdp_i64)
+TRANS(XVNEGDP, do_vsx_msb_op, MO_64, do_xvneg_vec, do_xvnegdp_i64)
+TRANS(XVABSSP, do_vsx_msb_op, MO_32, do_xvabs_vec, do_xvabssp_i64)
+TRANS(XVNABSSP, do_vsx_msb_op, MO_32, do_xvnabs_vec, do_xvnabssp_i64)
+TRANS(XVNEGSP, do_vsx_msb_op, MO_32, do_xvneg_vec, do_xvnegsp_i64)
+
+static void do_xvcpsgndp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
+{
+ tcg_gen_andi_i64(a, a, SGN_MASK_DP);
+ tcg_gen_andi_i64(b, b, ~SGN_MASK_DP);
+ tcg_gen_or_i64(t, a, b);
+}
+
+static void do_xvcpsgnsp_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b)
+{
+ tcg_gen_andi_i64(a, a, SGN_MASK_SP);
+ tcg_gen_andi_i64(b, b, ~SGN_MASK_SP);
+ tcg_gen_or_i64(t, a, b);
+}
+
+static void do_xvcpsgn_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b)
+{
+ uint64_t msb = (vece == MO_32) ? SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_bitsel_vec(vece, t, tcg_constant_vec_matching(t, vece, msb), a, b);
+}
+
+static bool do_xvcpsgn(DisasContext *ctx, arg_XX3 *a, unsigned vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ 0
+ };
+
+ static const GVecGen3 op[] = {
+ {
+ .fni8 = do_xvcpsgnsp_i64,
+ .fniv = do_xvcpsgn_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ {
+ .fni8 = do_xvcpsgndp_i64,
+ .fniv = do_xvcpsgn_vec,
+ .opt_opc = vecop_list,
+ .vece = MO_64
+ },
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_3(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
+ vsr_full_offset(a->xb), 16, 16, &op[vece - MO_32]);
+
+ return true;
+}
+
+TRANS(XVCPSGNSP, do_xvcpsgn, MO_32)
+TRANS(XVCPSGNDP, do_xvcpsgn, MO_64)
#define VSX_CMP(name, op1, op2, inval, type) \
static void gen_##name(DisasContext *ctx) \
@@ -1009,16 +801,11 @@ static void gen_##name(DisasContext *ctx) \
xa = gen_vsr_ptr(xA(ctx->opcode)); \
xb = gen_vsr_ptr(xB(ctx->opcode)); \
if ((ctx->opcode >> (31 - 21)) & 1) { \
- gen_helper_##name(cpu_crf[6], cpu_env, xt, xa, xb); \
+ gen_helper_##name(cpu_crf[6], tcg_env, xt, xa, xb); \
} else { \
ignored = tcg_temp_new_i32(); \
- gen_helper_##name(ignored, cpu_env, xt, xa, xb); \
- tcg_temp_free_i32(ignored); \
+ gen_helper_##name(ignored, tcg_env, xt, xa, xb); \
} \
- gen_helper_float_check_status(cpu_env); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(xb); \
}
VSX_CMP(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
@@ -1030,23 +817,41 @@ VSX_CMP(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
VSX_CMP(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
VSX_CMP(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX)
-static void gen_xscvqpdp(DisasContext *ctx)
+static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a)
{
- TCGv_i32 opc;
+ TCGv_i32 ro;
TCGv_ptr xt, xb;
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
- opc = tcg_const_i32(ctx->opcode);
- xt = gen_vsr_ptr(xT(ctx->opcode));
- xb = gen_vsr_ptr(xB(ctx->opcode));
- gen_helper_xscvqpdp(cpu_env, opc, xt, xb);
- tcg_temp_free_i32(opc);
- tcg_temp_free_ptr(xt);
- tcg_temp_free_ptr(xb);
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ ro = tcg_constant_i32(a->rc);
+
+ xt = gen_avr_ptr(a->rt);
+ xb = gen_avr_ptr(a->rb);
+ gen_helper_XSCVQPDP(tcg_env, ro, xt, xb);
+ return true;
+}
+
+static bool do_helper_env_X_tb(DisasContext *ctx, arg_X_tb *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr xt, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_avr_ptr(a->rt);
+ xb = gen_avr_ptr(a->rb);
+ gen_helper(tcg_env, xt, xb);
+ return true;
}
+TRANS(XSCVUQQP, do_helper_env_X_tb, gen_helper_XSCVUQQP)
+TRANS(XSCVSQQP, do_helper_env_X_tb, gen_helper_XSCVSQQP)
+TRANS(XSCVQPUQZ, do_helper_env_X_tb, gen_helper_XSCVQPUQZ)
+TRANS(XSCVQPSQZ, do_helper_env_X_tb, gen_helper_XSCVQPSQZ)
+
#define GEN_VSX_HELPER_2(name, op1, op2, inval, type) \
static void gen_##name(DisasContext *ctx) \
{ \
@@ -1055,9 +860,8 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
- gen_helper_##name(cpu_env, opc); \
- tcg_temp_free_i32(opc); \
+ opc = tcg_constant_i32(ctx->opcode); \
+ gen_helper_##name(tcg_env, opc); \
}
#define GEN_VSX_HELPER_X3(name, op1, op2, inval, type) \
@@ -1071,10 +875,7 @@ static void gen_##name(DisasContext *ctx) \
xt = gen_vsr_ptr(xT(ctx->opcode)); \
xa = gen_vsr_ptr(xA(ctx->opcode)); \
xb = gen_vsr_ptr(xB(ctx->opcode)); \
- gen_helper_##name(cpu_env, xt, xa, xb); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, xt, xa, xb); \
}
#define GEN_VSX_HELPER_X2(name, op1, op2, inval, type) \
@@ -1087,9 +888,7 @@ static void gen_##name(DisasContext *ctx) \
} \
xt = gen_vsr_ptr(xT(ctx->opcode)); \
xb = gen_vsr_ptr(xB(ctx->opcode)); \
- gen_helper_##name(cpu_env, xt, xb); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, xt, xb); \
}
#define GEN_VSX_HELPER_X2_AB(name, op1, op2, inval, type) \
@@ -1101,13 +900,10 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
+ opc = tcg_constant_i32(ctx->opcode); \
xa = gen_vsr_ptr(xA(ctx->opcode)); \
xb = gen_vsr_ptr(xB(ctx->opcode)); \
- gen_helper_##name(cpu_env, opc, xa, xb); \
- tcg_temp_free_i32(opc); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, opc, xa, xb); \
}
#define GEN_VSX_HELPER_X1(name, op1, op2, inval, type) \
@@ -1119,11 +915,9 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
+ opc = tcg_constant_i32(ctx->opcode); \
xb = gen_vsr_ptr(xB(ctx->opcode)); \
- gen_helper_##name(cpu_env, opc, xb); \
- tcg_temp_free_i32(opc); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, opc, xb); \
}
#define GEN_VSX_HELPER_R3(name, op1, op2, inval, type) \
@@ -1135,15 +929,11 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
+ opc = tcg_constant_i32(ctx->opcode); \
xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \
xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \
xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
- gen_helper_##name(cpu_env, opc, xt, xa, xb); \
- tcg_temp_free_i32(opc); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, opc, xt, xa, xb); \
}
#define GEN_VSX_HELPER_R2(name, op1, op2, inval, type) \
@@ -1155,13 +945,10 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
+ opc = tcg_constant_i32(ctx->opcode); \
xt = gen_vsr_ptr(rD(ctx->opcode) + 32); \
xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
- gen_helper_##name(cpu_env, opc, xt, xb); \
- tcg_temp_free_i32(opc); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, opc, xt, xb); \
}
#define GEN_VSX_HELPER_R2_AB(name, op1, op2, inval, type) \
@@ -1173,13 +960,10 @@ static void gen_##name(DisasContext *ctx) \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
- opc = tcg_const_i32(ctx->opcode); \
+ opc = tcg_constant_i32(ctx->opcode); \
xa = gen_vsr_ptr(rA(ctx->opcode) + 32); \
xb = gen_vsr_ptr(rB(ctx->opcode) + 32); \
- gen_helper_##name(cpu_env, opc, xa, xb); \
- tcg_temp_free_i32(opc); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(xb); \
+ gen_helper_##name(tcg_env, opc, xa, xb); \
}
#define GEN_VSX_HELPER_XT_XB_ENV(name, op1, op2, inval, type) \
@@ -1193,11 +977,10 @@ static void gen_##name(DisasContext *ctx) \
} \
t0 = tcg_temp_new_i64(); \
t1 = tcg_temp_new_i64(); \
- get_cpu_vsrh(t0, xB(ctx->opcode)); \
- gen_helper_##name(t1, cpu_env, t0); \
- set_cpu_vsrh(xT(ctx->opcode), t1); \
- tcg_temp_free_i64(t0); \
- tcg_temp_free_i64(t1); \
+ get_cpu_vsr(t0, xB(ctx->opcode), true); \
+ gen_helper_##name(t1, tcg_env, t0); \
+ set_cpu_vsr(xT(ctx->opcode), t1, true); \
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
}
GEN_VSX_HELPER_X3(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
@@ -1212,10 +995,6 @@ GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xsrsqrtedp, 0x14, 0x04, 0, PPC2_VSX)
GEN_VSX_HELPER_X2_AB(xstdivdp, 0x14, 0x07, 0, PPC2_VSX)
GEN_VSX_HELPER_X1(xstsqrtdp, 0x14, 0x06, 0, PPC2_VSX)
-GEN_VSX_HELPER_X3(xscmpeqdp, 0x0C, 0x00, 0, PPC2_ISA300)
-GEN_VSX_HELPER_X3(xscmpgtdp, 0x0C, 0x01, 0, PPC2_ISA300)
-GEN_VSX_HELPER_X3(xscmpgedp, 0x0C, 0x02, 0, PPC2_ISA300)
-GEN_VSX_HELPER_X3(xscmpnedp, 0x0C, 0x03, 0, PPC2_ISA300)
GEN_VSX_HELPER_X2_AB(xscmpexpdp, 0x0C, 0x07, 0, PPC2_ISA300)
GEN_VSX_HELPER_R2_AB(xscmpexpqp, 0x04, 0x05, 0, PPC2_ISA300)
GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
@@ -1224,10 +1003,6 @@ GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX)
GEN_VSX_HELPER_R2_AB(xscmpuqp, 0x04, 0x14, 0, PPC2_VSX)
GEN_VSX_HELPER_X3(xsmaxdp, 0x00, 0x14, 0, PPC2_VSX)
GEN_VSX_HELPER_X3(xsmindp, 0x00, 0x15, 0, PPC2_VSX)
-GEN_VSX_HELPER_R3(xsmaxcdp, 0x00, 0x10, 0, PPC2_ISA300)
-GEN_VSX_HELPER_R3(xsmincdp, 0x00, 0x11, 0, PPC2_ISA300)
-GEN_VSX_HELPER_R3(xsmaxjdp, 0x00, 0x12, 0, PPC2_ISA300)
-GEN_VSX_HELPER_R3(xsminjdp, 0x00, 0x12, 0, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
@@ -1239,7 +1014,208 @@ GEN_VSX_HELPER_R2(xscvqpuwz, 0x04, 0x1A, 0x01, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300)
GEN_VSX_HELPER_R2(xscvsdqp, 0x04, 0x1A, 0x0A, PPC2_ISA300)
GEN_VSX_HELPER_X2(xscvspdp, 0x12, 0x14, 0, PPC2_VSX)
-GEN_VSX_HELPER_XT_XB_ENV(xscvspdpn, 0x16, 0x14, 0, PPC2_VSX207)
+
+/* test if +Inf */
+static void gen_is_pos_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, exp_msk));
+}
+
+/* test if -Inf */
+static void gen_is_neg_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk | exp_msk));
+}
+
+/* test if +Inf or -Inf */
+static void gen_is_any_inf(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, exp_msk));
+}
+
+/* test if +0 */
+static void gen_is_pos_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, 0));
+}
+
+/* test if -0 */
+static void gen_is_neg_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk));
+}
+
+/* test if +0 or -0 */
+static void gen_is_any_zero(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_EQ, vece, t, b,
+ tcg_constant_vec_matching(t, vece, 0));
+}
+
+/* test if +Denormal */
+static void gen_is_pos_denormal(unsigned vece, TCGv_vec t,
+ TCGv_vec b, int64_t v)
+{
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
+ tcg_constant_vec_matching(t, vece, frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
+ tcg_constant_vec_matching(t, vece, 0));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if -Denormal */
+static void gen_is_neg_denormal(unsigned vece, TCGv_vec t,
+ TCGv_vec b, int64_t v)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_cmp_vec(TCG_COND_LEU, vece, t, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk | frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_GTU, vece, b, b,
+ tcg_constant_vec_matching(t, vece, sgn_msk));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if +Denormal or -Denormal */
+static void gen_is_any_denormal(unsigned vece, TCGv_vec t,
+ TCGv_vec b, int64_t v)
+{
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ uint64_t frc_msk = (vece == MO_32) ? (uint32_t)FRC_MASK_SP : FRC_MASK_DP;
+ tcg_gen_andc_vec(vece, b, b, tcg_constant_vec_matching(t, vece, sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_LE, vece, t, b,
+ tcg_constant_vec_matching(t, vece, frc_msk));
+ tcg_gen_cmp_vec(TCG_COND_NE, vece, b, b,
+ tcg_constant_vec_matching(t, vece, 0));
+ tcg_gen_and_vec(vece, t, t, b);
+}
+
+/* test if NaN */
+static void gen_is_nan(unsigned vece, TCGv_vec t, TCGv_vec b, int64_t v)
+{
+ uint64_t exp_msk = (vece == MO_32) ? (uint32_t)EXP_MASK_SP : EXP_MASK_DP;
+ uint64_t sgn_msk = (vece == MO_32) ? (uint32_t)SGN_MASK_SP : SGN_MASK_DP;
+ tcg_gen_and_vec(vece, b, b, tcg_constant_vec_matching(t, vece, ~sgn_msk));
+ tcg_gen_cmp_vec(TCG_COND_GT, vece, t, b,
+ tcg_constant_vec_matching(t, vece, exp_msk));
+}
+
+static bool do_xvtstdc(DisasContext *ctx, arg_XX2_uim *a, unsigned vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_cmp_vec, 0
+ };
+
+ GVecGen2i op = {
+ .fnoi = (vece == MO_32) ? gen_helper_XVTSTDCSP : gen_helper_XVTSTDCDP,
+ .vece = vece,
+ .opt_opc = vecop_list
+ };
+
+ REQUIRE_VSX(ctx);
+
+ switch (a->uim) {
+ case 0:
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
+ return true;
+ case ((1 << 0) | (1 << 1)):
+ /* test if +Denormal or -Denormal */
+ op.fniv = gen_is_any_denormal;
+ break;
+ case (1 << 0):
+ /* test if -Denormal */
+ op.fniv = gen_is_neg_denormal;
+ break;
+ case (1 << 1):
+ /* test if +Denormal */
+ op.fniv = gen_is_pos_denormal;
+ break;
+ case ((1 << 2) | (1 << 3)):
+ /* test if +0 or -0 */
+ op.fniv = gen_is_any_zero;
+ break;
+ case (1 << 2):
+ /* test if -0 */
+ op.fniv = gen_is_neg_zero;
+ break;
+ case (1 << 3):
+ /* test if +0 */
+ op.fniv = gen_is_pos_zero;
+ break;
+ case ((1 << 4) | (1 << 5)):
+ /* test if +Inf or -Inf */
+ op.fniv = gen_is_any_inf;
+ break;
+ case (1 << 4):
+ /* test if -Inf */
+ op.fniv = gen_is_neg_inf;
+ break;
+ case (1 << 5):
+ /* test if +Inf */
+ op.fniv = gen_is_pos_inf;
+ break;
+ case (1 << 6):
+ /* test if NaN */
+ op.fniv = gen_is_nan;
+ break;
+ }
+ tcg_gen_gvec_2i(vsr_full_offset(a->xt), vsr_full_offset(a->xb),
+ 16, 16, a->uim, &op);
+
+ return true;
+}
+
+TRANS_FLAGS2(VSX, XVTSTDCSP, do_xvtstdc, MO_32)
+TRANS_FLAGS2(VSX, XVTSTDCDP, do_xvtstdc, MO_64)
+
+static bool do_XX2_bf_uim(DisasContext *ctx, arg_XX2_bf_uim *a, bool vsr,
+ void (*gen_helper)(TCGv_env, TCGv_i32, TCGv_i32, TCGv_ptr))
+{
+ TCGv_ptr xb;
+
+ REQUIRE_VSX(ctx);
+ xb = vsr ? gen_vsr_ptr(a->xb) : gen_avr_ptr(a->xb);
+ gen_helper(tcg_env, tcg_constant_i32(a->bf), tcg_constant_i32(a->uim), xb);
+ return true;
+}
+
+TRANS_FLAGS2(ISA300, XSTSTDCSP, do_XX2_bf_uim, true, gen_helper_XSTSTDCSP)
+TRANS_FLAGS2(ISA300, XSTSTDCDP, do_XX2_bf_uim, true, gen_helper_XSTSTDCDP)
+TRANS_FLAGS2(ISA300, XSTSTDCQP, do_XX2_bf_uim, false, gen_helper_XSTSTDCQP)
+
+bool trans_XSCVSPDPN(DisasContext *ctx, arg_XX2 *a)
+{
+ TCGv_i64 tmp;
+
+ REQUIRE_INSNS_FLAGS2(ctx, VSX207);
+ REQUIRE_VSX(ctx);
+
+ tmp = tcg_temp_new_i64();
+ get_cpu_vsr(tmp, a->xb, true);
+
+ gen_helper_XSCVSPDPN(tmp, tmp);
+
+ set_cpu_vsr(a->xt, tmp, true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
+ return true;
+}
+
GEN_VSX_HELPER_X2(xscvdpsxds, 0x10, 0x15, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xscvdpsxws, 0x10, 0x05, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xscvdpuxds, 0x10, 0x14, 0, PPC2_VSX)
@@ -1266,9 +1242,6 @@ GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 0x00, 0, PPC2_VSX207)
GEN_VSX_HELPER_X2(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
-GEN_VSX_HELPER_X1(xststdcsp, 0x14, 0x12, 0, PPC2_ISA300)
-GEN_VSX_HELPER_2(xststdcdp, 0x14, 0x16, 0, PPC2_ISA300)
-GEN_VSX_HELPER_2(xststdcqp, 0x04, 0x16, 0, PPC2_ISA300)
GEN_VSX_HELPER_X3(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
GEN_VSX_HELPER_X3(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
@@ -1323,49 +1296,213 @@ GEN_VSX_HELPER_X2(xvrspic, 0x16, 0x0A, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xvrspim, 0x12, 0x0B, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xvrspip, 0x12, 0x0A, 0, PPC2_VSX)
GEN_VSX_HELPER_X2(xvrspiz, 0x12, 0x09, 0, PPC2_VSX)
-GEN_VSX_HELPER_2(xvtstdcsp, 0x14, 0x1A, 0, PPC2_VSX)
-GEN_VSX_HELPER_2(xvtstdcdp, 0x14, 0x1E, 0, PPC2_VSX)
-GEN_VSX_HELPER_X3(xxperm, 0x08, 0x03, 0, PPC2_ISA300)
-GEN_VSX_HELPER_X3(xxpermr, 0x08, 0x07, 0, PPC2_ISA300)
+
+static bool trans_XXPERM(DisasContext *ctx, arg_XX3 *a)
+{
+ TCGv_ptr xt, xa, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_vsr_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+
+ gen_helper_VPERM(xt, xa, xt, xb);
+ return true;
+}
+
+static bool trans_XXPERMR(DisasContext *ctx, arg_XX3 *a)
+{
+ TCGv_ptr xt, xa, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_vsr_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+
+ gen_helper_VPERMR(xt, xa, xt, xb);
+ return true;
+}
+
+static bool trans_XXPERMDI(DisasContext *ctx, arg_XX3_dm *a)
+{
+ TCGv_i64 t0, t1;
+
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
+ REQUIRE_VSX(ctx);
+
+ t0 = tcg_temp_new_i64();
+
+ if (unlikely(a->xt == a->xa || a->xt == a->xb)) {
+ t1 = tcg_temp_new_i64();
+
+ get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
+ get_cpu_vsr(t1, a->xb, (a->dm & 1) == 0);
+
+ set_cpu_vsr(a->xt, t0, true);
+ set_cpu_vsr(a->xt, t1, false);
+ } else {
+ get_cpu_vsr(t0, a->xa, (a->dm & 2) == 0);
+ set_cpu_vsr(a->xt, t0, true);
+
+ get_cpu_vsr(t0, a->xb, (a->dm & 1) == 0);
+ set_cpu_vsr(a->xt, t0, false);
+ }
+ return true;
+}
+
+static bool trans_XXPERMX(DisasContext *ctx, arg_8RR_XX4_uim3 *a)
+{
+ TCGv_ptr xt, xa, xb, xc;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_vsr_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+ xc = gen_vsr_ptr(a->xc);
+
+ gen_helper_XXPERMX(xt, xa, xb, xc, tcg_constant_tl(a->uim3));
+ return true;
+}
+
+typedef void (*xxgenpcv_genfn)(TCGv_ptr, TCGv_ptr);
+
+static bool do_xxgenpcv(DisasContext *ctx, arg_X_imm5 *a,
+ const xxgenpcv_genfn fn[4])
+{
+ TCGv_ptr xt, vrb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ if (a->imm & ~0x3) {
+ gen_invalid(ctx);
+ return true;
+ }
+
+ xt = gen_vsr_ptr(a->xt);
+ vrb = gen_avr_ptr(a->vrb);
+
+ fn[a->imm](xt, vrb);
+ return true;
+}
+
+#define XXGENPCV(NAME) \
+ static bool trans_##NAME(DisasContext *ctx, arg_X_imm5 *a) \
+ { \
+ static const xxgenpcv_genfn fn[4] = { \
+ gen_helper_##NAME##_be_exp, \
+ gen_helper_##NAME##_be_comp, \
+ gen_helper_##NAME##_le_exp, \
+ gen_helper_##NAME##_le_comp, \
+ }; \
+ return do_xxgenpcv(ctx, a, fn); \
+ }
+
+XXGENPCV(XXGENPCVBM)
+XXGENPCV(XXGENPCVHM)
+XXGENPCV(XXGENPCVWM)
+XXGENPCV(XXGENPCVDM)
+#undef XXGENPCV
+
+static bool do_xsmadd(DisasContext *ctx, int tgt, int src1, int src2, int src3,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr t, s1, s2, s3;
+
+ t = gen_vsr_ptr(tgt);
+ s1 = gen_vsr_ptr(src1);
+ s2 = gen_vsr_ptr(src2);
+ s3 = gen_vsr_ptr(src3);
+
+ gen_helper(tcg_env, t, s1, s2, s3);
+ return true;
+}
+
+static bool do_xsmadd_XX3(DisasContext *ctx, arg_XX3 *a, bool type_a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ REQUIRE_VSX(ctx);
+
+ if (type_a) {
+ return do_xsmadd(ctx, a->xt, a->xa, a->xt, a->xb, gen_helper);
+ }
+ return do_xsmadd(ctx, a->xt, a->xa, a->xb, a->xt, gen_helper);
+}
+
+TRANS_FLAGS2(VSX, XSMADDADP, do_xsmadd_XX3, true, gen_helper_XSMADDDP)
+TRANS_FLAGS2(VSX, XSMADDMDP, do_xsmadd_XX3, false, gen_helper_XSMADDDP)
+TRANS_FLAGS2(VSX, XSMSUBADP, do_xsmadd_XX3, true, gen_helper_XSMSUBDP)
+TRANS_FLAGS2(VSX, XSMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSMSUBDP)
+TRANS_FLAGS2(VSX, XSNMADDADP, do_xsmadd_XX3, true, gen_helper_XSNMADDDP)
+TRANS_FLAGS2(VSX, XSNMADDMDP, do_xsmadd_XX3, false, gen_helper_XSNMADDDP)
+TRANS_FLAGS2(VSX, XSNMSUBADP, do_xsmadd_XX3, true, gen_helper_XSNMSUBDP)
+TRANS_FLAGS2(VSX, XSNMSUBMDP, do_xsmadd_XX3, false, gen_helper_XSNMSUBDP)
+TRANS_FLAGS2(VSX207, XSMADDASP, do_xsmadd_XX3, true, gen_helper_XSMADDSP)
+TRANS_FLAGS2(VSX207, XSMADDMSP, do_xsmadd_XX3, false, gen_helper_XSMADDSP)
+TRANS_FLAGS2(VSX207, XSMSUBASP, do_xsmadd_XX3, true, gen_helper_XSMSUBSP)
+TRANS_FLAGS2(VSX207, XSMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSMSUBSP)
+TRANS_FLAGS2(VSX207, XSNMADDASP, do_xsmadd_XX3, true, gen_helper_XSNMADDSP)
+TRANS_FLAGS2(VSX207, XSNMADDMSP, do_xsmadd_XX3, false, gen_helper_XSNMADDSP)
+TRANS_FLAGS2(VSX207, XSNMSUBASP, do_xsmadd_XX3, true, gen_helper_XSNMSUBSP)
+TRANS_FLAGS2(VSX207, XSNMSUBMSP, do_xsmadd_XX3, false, gen_helper_XSNMSUBSP)
+
+static bool do_xsmadd_X(DisasContext *ctx, arg_X_rc *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr),
+ void (*gen_helper_ro)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ int vrt, vra, vrb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ vrt = a->rt + 32;
+ vra = a->ra + 32;
+ vrb = a->rb + 32;
+
+ if (a->rc) {
+ return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper_ro);
+ }
+
+ return do_xsmadd(ctx, vrt, vra, vrt, vrb, gen_helper);
+}
+
+TRANS(XSMADDQP, do_xsmadd_X, gen_helper_XSMADDQP, gen_helper_XSMADDQPO)
+TRANS(XSMSUBQP, do_xsmadd_X, gen_helper_XSMSUBQP, gen_helper_XSMSUBQPO)
+TRANS(XSNMADDQP, do_xsmadd_X, gen_helper_XSNMADDQP, gen_helper_XSNMADDQPO)
+TRANS(XSNMSUBQP, do_xsmadd_X, gen_helper_XSNMSUBQP, gen_helper_XSNMSUBQPO)
#define GEN_VSX_HELPER_VSX_MADD(name, op1, aop, mop, inval, type) \
static void gen_##name(DisasContext *ctx) \
{ \
- TCGv_ptr xt, xa, b, c; \
+ TCGv_ptr xt, s1, s2, s3; \
if (unlikely(!ctx->vsx_enabled)) { \
gen_exception(ctx, POWERPC_EXCP_VSXU); \
return; \
} \
xt = gen_vsr_ptr(xT(ctx->opcode)); \
- xa = gen_vsr_ptr(xA(ctx->opcode)); \
+ s1 = gen_vsr_ptr(xA(ctx->opcode)); \
if (ctx->opcode & PPC_BIT32(25)) { \
/* \
* AxT + B \
*/ \
- b = gen_vsr_ptr(xT(ctx->opcode)); \
- c = gen_vsr_ptr(xB(ctx->opcode)); \
+ s2 = gen_vsr_ptr(xB(ctx->opcode)); \
+ s3 = gen_vsr_ptr(xT(ctx->opcode)); \
} else { \
/* \
* AxB + T \
*/ \
- b = gen_vsr_ptr(xB(ctx->opcode)); \
- c = gen_vsr_ptr(xT(ctx->opcode)); \
+ s2 = gen_vsr_ptr(xT(ctx->opcode)); \
+ s3 = gen_vsr_ptr(xB(ctx->opcode)); \
} \
- gen_helper_##name(cpu_env, xt, xa, b, c); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_ptr(xa); \
- tcg_temp_free_ptr(b); \
- tcg_temp_free_ptr(c); \
-}
-
-GEN_VSX_HELPER_VSX_MADD(xsmadddp, 0x04, 0x04, 0x05, 0, PPC2_VSX)
-GEN_VSX_HELPER_VSX_MADD(xsmsubdp, 0x04, 0x06, 0x07, 0, PPC2_VSX)
-GEN_VSX_HELPER_VSX_MADD(xsnmadddp, 0x04, 0x14, 0x15, 0, PPC2_VSX)
-GEN_VSX_HELPER_VSX_MADD(xsnmsubdp, 0x04, 0x16, 0x17, 0, PPC2_VSX)
-GEN_VSX_HELPER_VSX_MADD(xsmaddsp, 0x04, 0x00, 0x01, 0, PPC2_VSX207)
-GEN_VSX_HELPER_VSX_MADD(xsmsubsp, 0x04, 0x02, 0x03, 0, PPC2_VSX207)
-GEN_VSX_HELPER_VSX_MADD(xsnmaddsp, 0x04, 0x10, 0x11, 0, PPC2_VSX207)
-GEN_VSX_HELPER_VSX_MADD(xsnmsubsp, 0x04, 0x12, 0x13, 0, PPC2_VSX207)
+ gen_helper_##name(tcg_env, xt, s1, s2, s3); \
+}
+
GEN_VSX_HELPER_VSX_MADD(xvmadddp, 0x04, 0x0C, 0x0D, 0, PPC2_VSX)
GEN_VSX_HELPER_VSX_MADD(xvmsubdp, 0x04, 0x0E, 0x0F, 0, PPC2_VSX)
GEN_VSX_HELPER_VSX_MADD(xvnmadddp, 0x04, 0x1C, 0x1D, 0, PPC2_VSX)
@@ -1390,18 +1527,13 @@ static void gen_xxbrd(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
tcg_gen_bswap64_i64(xth, xbh);
tcg_gen_bswap64_i64(xtl, xbl);
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_xxbrh(DisasContext *ctx)
@@ -1419,17 +1551,12 @@ static void gen_xxbrh(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
gen_bswap16x8(xth, xtl, xbh, xbl);
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_xxbrq(DisasContext *ctx)
@@ -1448,21 +1575,15 @@ static void gen_xxbrq(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
t0 = tcg_temp_new_i64();
tcg_gen_bswap64_i64(t0, xbl);
tcg_gen_bswap64_i64(xtl, xbh);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
tcg_gen_mov_i64(xth, t0);
- set_cpu_vsrh(xT(ctx->opcode), xth);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
}
static void gen_xxbrw(DisasContext *ctx)
@@ -1480,17 +1601,12 @@ static void gen_xxbrw(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
gen_bswap32x4(xth, xtl, xbh, xbl);
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
#define VSX_LOGICAL(name, vece, tcg_op) \
@@ -1527,89 +1643,173 @@ static void glue(gen_, name)(DisasContext *ctx) \
b0 = tcg_temp_new_i64(); \
b1 = tcg_temp_new_i64(); \
tmp = tcg_temp_new_i64(); \
- if (high) { \
- get_cpu_vsrh(a0, xA(ctx->opcode)); \
- get_cpu_vsrh(a1, xA(ctx->opcode)); \
- get_cpu_vsrh(b0, xB(ctx->opcode)); \
- get_cpu_vsrh(b1, xB(ctx->opcode)); \
- } else { \
- get_cpu_vsrl(a0, xA(ctx->opcode)); \
- get_cpu_vsrl(a1, xA(ctx->opcode)); \
- get_cpu_vsrl(b0, xB(ctx->opcode)); \
- get_cpu_vsrl(b1, xB(ctx->opcode)); \
- } \
+ get_cpu_vsr(a0, xA(ctx->opcode), high); \
+ get_cpu_vsr(a1, xA(ctx->opcode), high); \
+ get_cpu_vsr(b0, xB(ctx->opcode), high); \
+ get_cpu_vsr(b1, xB(ctx->opcode), high); \
tcg_gen_shri_i64(a0, a0, 32); \
tcg_gen_shri_i64(b0, b0, 32); \
tcg_gen_deposit_i64(tmp, b0, a0, 32, 32); \
- set_cpu_vsrh(xT(ctx->opcode), tmp); \
+ set_cpu_vsr(xT(ctx->opcode), tmp, true); \
tcg_gen_deposit_i64(tmp, b1, a1, 32, 32); \
- set_cpu_vsrl(xT(ctx->opcode), tmp); \
- tcg_temp_free_i64(a0); \
- tcg_temp_free_i64(a1); \
- tcg_temp_free_i64(b0); \
- tcg_temp_free_i64(b1); \
- tcg_temp_free_i64(tmp); \
+ set_cpu_vsr(xT(ctx->opcode), tmp, false); \
}
VSX_XXMRG(xxmrghw, 1)
VSX_XXMRG(xxmrglw, 0)
-static void gen_xxsel(DisasContext *ctx)
+static bool trans_XXSEL(DisasContext *ctx, arg_XX4 *a)
{
- int rt = xT(ctx->opcode);
- int ra = xA(ctx->opcode);
- int rb = xB(ctx->opcode);
- int rc = xC(ctx->opcode);
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
+ REQUIRE_VSX(ctx);
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
- tcg_gen_gvec_bitsel(MO_64, vsr_full_offset(rt), vsr_full_offset(rc),
- vsr_full_offset(rb), vsr_full_offset(ra), 16, 16);
+ tcg_gen_gvec_bitsel(MO_64, vsr_full_offset(a->xt), vsr_full_offset(a->xc),
+ vsr_full_offset(a->xb), vsr_full_offset(a->xa), 16, 16);
+
+ return true;
}
-static void gen_xxspltw(DisasContext *ctx)
+static bool trans_XXSPLTW(DisasContext *ctx, arg_XX2_uim *a)
{
- int rt = xT(ctx->opcode);
- int rb = xB(ctx->opcode);
- int uim = UIM(ctx->opcode);
int tofs, bofs;
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
+ REQUIRE_VSX(ctx);
- tofs = vsr_full_offset(rt);
- bofs = vsr_full_offset(rb);
- bofs += uim << MO_32;
-#ifndef HOST_WORDS_BIG_ENDIAN
+ tofs = vsr_full_offset(a->xt);
+ bofs = vsr_full_offset(a->xb);
+ bofs += a->uim << MO_32;
+#if !HOST_BIG_ENDIAN
bofs ^= 8 | 4;
#endif
tcg_gen_gvec_dup_mem(MO_32, tofs, bofs, 16, 16);
+ return true;
}
#define pattern(x) (((x) & 0xff) * (~(uint64_t)0 / 0xff))
-static void gen_xxspltib(DisasContext *ctx)
+static bool trans_XXSPLTIB(DisasContext *ctx, arg_X_imm8 *a)
{
- uint8_t uim8 = IMM8(ctx->opcode);
- int rt = xT(ctx->opcode);
+ if (a->xt < 32) {
+ REQUIRE_VSX(ctx);
+ } else {
+ REQUIRE_VECTOR(ctx);
+ }
+ tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(a->xt), 16, 16, a->imm);
+ return true;
+}
- if (rt < 32) {
- if (unlikely(!ctx->vsx_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VSXU);
- return;
- }
+static bool trans_XXSPLTIW(DisasContext *ctx, arg_8RR_D *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_dup_imm(MO_32, vsr_full_offset(a->xt), 16, 16, a->si);
+
+ return true;
+}
+
+static bool trans_XXSPLTIDP(DisasContext *ctx, arg_8RR_D *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_dup_imm(MO_64, vsr_full_offset(a->xt), 16, 16,
+ helper_todouble(a->si));
+ return true;
+}
+
+static bool trans_XXSPLTI32DX(DisasContext *ctx, arg_8RR_D_IX *a)
+{
+ TCGv_i32 imm;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ imm = tcg_constant_i32(a->si);
+
+ tcg_gen_st_i32(imm, tcg_env,
+ offsetof(CPUPPCState, vsr[a->xt].VsrW(0 + a->ix)));
+ tcg_gen_st_i32(imm, tcg_env,
+ offsetof(CPUPPCState, vsr[a->xt].VsrW(2 + a->ix)));
+
+ return true;
+}
+
+static bool trans_LXVKQ(DisasContext *ctx, arg_X_uim5 *a)
+{
+ static const uint64_t values[32] = {
+ 0, /* Unspecified */
+ 0x3FFF000000000000llu, /* QP +1.0 */
+ 0x4000000000000000llu, /* QP +2.0 */
+ 0x4000800000000000llu, /* QP +3.0 */
+ 0x4001000000000000llu, /* QP +4.0 */
+ 0x4001400000000000llu, /* QP +5.0 */
+ 0x4001800000000000llu, /* QP +6.0 */
+ 0x4001C00000000000llu, /* QP +7.0 */
+ 0x7FFF000000000000llu, /* QP +Inf */
+ 0x7FFF800000000000llu, /* QP dQNaN */
+ 0, /* Unspecified */
+ 0, /* Unspecified */
+ 0, /* Unspecified */
+ 0, /* Unspecified */
+ 0, /* Unspecified */
+ 0, /* Unspecified */
+ 0x8000000000000000llu, /* QP -0.0 */
+ 0xBFFF000000000000llu, /* QP -1.0 */
+ 0xC000000000000000llu, /* QP -2.0 */
+ 0xC000800000000000llu, /* QP -3.0 */
+ 0xC001000000000000llu, /* QP -4.0 */
+ 0xC001400000000000llu, /* QP -5.0 */
+ 0xC001800000000000llu, /* QP -6.0 */
+ 0xC001C00000000000llu, /* QP -7.0 */
+ 0xFFFF000000000000llu, /* QP -Inf */
+ };
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ if (values[a->uim]) {
+ set_cpu_vsr(a->xt, tcg_constant_i64(0x0), false);
+ set_cpu_vsr(a->xt, tcg_constant_i64(values[a->uim]), true);
} else {
- if (unlikely(!ctx->altivec_enabled)) {
- gen_exception(ctx, POWERPC_EXCP_VPU);
- return;
- }
+ gen_invalid(ctx);
}
- tcg_gen_gvec_dup_imm(MO_8, vsr_full_offset(rt), 16, 16, uim8);
+
+ return true;
+}
+
+static bool trans_XVTLSBB(DisasContext *ctx, arg_XX2_bf_xb *a)
+{
+ TCGv_i64 xb, t0, t1, all_true, all_false, mask, zero;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ xb = tcg_temp_new_i64();
+ t0 = tcg_temp_new_i64();
+ t1 = tcg_temp_new_i64();
+ all_true = tcg_temp_new_i64();
+ all_false = tcg_temp_new_i64();
+ mask = tcg_constant_i64(dup_const(MO_8, 1));
+ zero = tcg_constant_i64(0);
+
+ get_cpu_vsr(xb, a->xb, true);
+ tcg_gen_and_i64(t0, mask, xb);
+ get_cpu_vsr(xb, a->xb, false);
+ tcg_gen_and_i64(t1, mask, xb);
+
+ tcg_gen_or_i64(all_false, t0, t1);
+ tcg_gen_and_i64(all_true, t0, t1);
+
+ tcg_gen_setcond_i64(TCG_COND_EQ, all_false, all_false, zero);
+ tcg_gen_shli_i64(all_false, all_false, 1);
+ tcg_gen_setcond_i64(TCG_COND_EQ, all_true, all_true, mask);
+ tcg_gen_shli_i64(all_true, all_true, 3);
+
+ tcg_gen_or_i64(t0, all_false, all_true);
+ tcg_gen_extrl_i64_i32(cpu_crf[a->bf], t0);
+ return true;
}
static void gen_xxsldwi(DisasContext *ctx)
@@ -1624,90 +1824,75 @@ static void gen_xxsldwi(DisasContext *ctx)
switch (SHW(ctx->opcode)) {
case 0: {
- get_cpu_vsrh(xth, xA(ctx->opcode));
- get_cpu_vsrl(xtl, xA(ctx->opcode));
+ get_cpu_vsr(xth, xA(ctx->opcode), true);
+ get_cpu_vsr(xtl, xA(ctx->opcode), false);
break;
}
case 1: {
TCGv_i64 t0 = tcg_temp_new_i64();
- get_cpu_vsrh(xth, xA(ctx->opcode));
+ get_cpu_vsr(xth, xA(ctx->opcode), true);
tcg_gen_shli_i64(xth, xth, 32);
- get_cpu_vsrl(t0, xA(ctx->opcode));
+ get_cpu_vsr(t0, xA(ctx->opcode), false);
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xth, xth, t0);
- get_cpu_vsrl(xtl, xA(ctx->opcode));
+ get_cpu_vsr(xtl, xA(ctx->opcode), false);
tcg_gen_shli_i64(xtl, xtl, 32);
- get_cpu_vsrh(t0, xB(ctx->opcode));
+ get_cpu_vsr(t0, xB(ctx->opcode), true);
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xtl, xtl, t0);
- tcg_temp_free_i64(t0);
break;
}
case 2: {
- get_cpu_vsrl(xth, xA(ctx->opcode));
- get_cpu_vsrh(xtl, xB(ctx->opcode));
+ get_cpu_vsr(xth, xA(ctx->opcode), false);
+ get_cpu_vsr(xtl, xB(ctx->opcode), true);
break;
}
case 3: {
TCGv_i64 t0 = tcg_temp_new_i64();
- get_cpu_vsrl(xth, xA(ctx->opcode));
+ get_cpu_vsr(xth, xA(ctx->opcode), false);
tcg_gen_shli_i64(xth, xth, 32);
- get_cpu_vsrh(t0, xB(ctx->opcode));
+ get_cpu_vsr(t0, xB(ctx->opcode), true);
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xth, xth, t0);
- get_cpu_vsrh(xtl, xB(ctx->opcode));
+ get_cpu_vsr(xtl, xB(ctx->opcode), true);
tcg_gen_shli_i64(xtl, xtl, 32);
- get_cpu_vsrl(t0, xB(ctx->opcode));
+ get_cpu_vsr(t0, xB(ctx->opcode), false);
tcg_gen_shri_i64(t0, t0, 32);
tcg_gen_or_i64(xtl, xtl, t0);
- tcg_temp_free_i64(t0);
break;
}
}
- set_cpu_vsrh(xT(ctx->opcode), xth);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
-}
-
-#define VSX_EXTRACT_INSERT(name) \
-static void gen_##name(DisasContext *ctx) \
-{ \
- TCGv_ptr xt, xb; \
- TCGv_i32 t0; \
- TCGv_i64 t1; \
- uint8_t uimm = UIMM4(ctx->opcode); \
- \
- if (unlikely(!ctx->vsx_enabled)) { \
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
- return; \
- } \
- xt = gen_vsr_ptr(xT(ctx->opcode)); \
- xb = gen_vsr_ptr(xB(ctx->opcode)); \
- t0 = tcg_temp_new_i32(); \
- t1 = tcg_temp_new_i64(); \
- /* \
- * uimm > 15 out of bound and for \
- * uimm > 12 handle as per hardware in helper \
- */ \
- if (uimm > 15) { \
- tcg_gen_movi_i64(t1, 0); \
- set_cpu_vsrh(xT(ctx->opcode), t1); \
- set_cpu_vsrl(xT(ctx->opcode), t1); \
- return; \
- } \
- tcg_gen_movi_i32(t0, uimm); \
- gen_helper_##name(cpu_env, xt, xb, t0); \
- tcg_temp_free_ptr(xb); \
- tcg_temp_free_ptr(xt); \
- tcg_temp_free_i32(t0); \
- tcg_temp_free_i64(t1); \
-}
-
-VSX_EXTRACT_INSERT(xxextractuw)
-VSX_EXTRACT_INSERT(xxinsertw)
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
+}
+
+static bool do_vsx_extract_insert(DisasContext *ctx, arg_XX2_uim *a,
+ void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i32))
+{
+ TCGv_i64 zero = tcg_constant_i64(0);
+ TCGv_ptr xt, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ /*
+ * uim > 15 out of bound and for
+ * uim > 12 handle as per hardware in helper
+ */
+ if (a->uim > 15) {
+ set_cpu_vsr(a->xt, zero, true);
+ set_cpu_vsr(a->xt, zero, false);
+ } else {
+ xt = gen_vsr_ptr(a->xt);
+ xb = gen_vsr_ptr(a->xb);
+ gen_helper(xt, xb, tcg_constant_i32(a->uim));
+ }
+ return true;
+}
+
+TRANS(XXEXTRACTUW, do_vsx_extract_insert, gen_helper_XXEXTRACTUW)
+TRANS(XXINSERTW, do_vsx_extract_insert, gen_helper_XXINSERTW)
#ifdef TARGET_PPC64
static void gen_xsxexpdp(DisasContext *ctx)
@@ -1719,9 +1904,8 @@ static void gen_xsxexpdp(DisasContext *ctx)
return;
}
t0 = tcg_temp_new_i64();
- get_cpu_vsrh(t0, xB(ctx->opcode));
+ get_cpu_vsr(t0, xB(ctx->opcode), true);
tcg_gen_extract_i64(rt, t0, 52, 11);
- tcg_temp_free_i64(t0);
}
static void gen_xsxexpqp(DisasContext *ctx)
@@ -1737,16 +1921,12 @@ static void gen_xsxexpqp(DisasContext *ctx)
xth = tcg_temp_new_i64();
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
+ get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
tcg_gen_extract_i64(xth, xbh, 48, 15);
- set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
tcg_gen_movi_i64(xtl, 0);
- set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
-
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
}
static void gen_xsiexpdp(DisasContext *ctx)
@@ -1766,10 +1946,8 @@ static void gen_xsiexpdp(DisasContext *ctx)
tcg_gen_andi_i64(t0, rb, 0x7FF);
tcg_gen_shli_i64(t0, t0, 52);
tcg_gen_or_i64(xth, xth, t0);
- set_cpu_vsrh(xT(ctx->opcode), xth);
- /* dword[1] is undefined */
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
+ set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false);
}
static void gen_xsiexpqp(DisasContext *ctx)
@@ -1789,26 +1967,19 @@ static void gen_xsiexpqp(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xah = tcg_temp_new_i64();
xal = tcg_temp_new_i64();
- get_cpu_vsrh(xah, rA(ctx->opcode) + 32);
- get_cpu_vsrl(xal, rA(ctx->opcode) + 32);
+ get_cpu_vsr(xah, rA(ctx->opcode) + 32, true);
+ get_cpu_vsr(xal, rA(ctx->opcode) + 32, false);
xbh = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
+ get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
t0 = tcg_temp_new_i64();
tcg_gen_andi_i64(xth, xah, 0x8000FFFFFFFFFFFF);
tcg_gen_andi_i64(t0, xbh, 0x7FFF);
tcg_gen_shli_i64(t0, t0, 48);
tcg_gen_or_i64(xth, xth, t0);
- set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
tcg_gen_mov_i64(xtl, xal);
- set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xah);
- tcg_temp_free_i64(xal);
- tcg_temp_free_i64(xbh);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
}
static void gen_xsxsigdp(DisasContext *ctx)
@@ -1823,22 +1994,16 @@ static void gen_xsxsigdp(DisasContext *ctx)
exp = tcg_temp_new_i64();
t0 = tcg_temp_new_i64();
t1 = tcg_temp_new_i64();
- zr = tcg_const_i64(0);
- nan = tcg_const_i64(2047);
+ zr = tcg_constant_i64(0);
+ nan = tcg_constant_i64(2047);
- get_cpu_vsrh(t1, xB(ctx->opcode));
+ get_cpu_vsr(t1, xB(ctx->opcode), true);
tcg_gen_extract_i64(exp, t1, 52, 11);
tcg_gen_movi_i64(t0, 0x0010000000000000);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
- get_cpu_vsrh(t1, xB(ctx->opcode));
+ get_cpu_vsr(t1, xB(ctx->opcode), true);
tcg_gen_deposit_i64(rt, t0, t1, 0, 52);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(t1);
- tcg_temp_free_i64(exp);
- tcg_temp_free_i64(zr);
- tcg_temp_free_i64(nan);
}
static void gen_xsxsigqp(DisasContext *ctx)
@@ -1857,30 +2022,21 @@ static void gen_xsxsigqp(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, rB(ctx->opcode) + 32);
- get_cpu_vsrl(xbl, rB(ctx->opcode) + 32);
+ get_cpu_vsr(xbh, rB(ctx->opcode) + 32, true);
+ get_cpu_vsr(xbl, rB(ctx->opcode) + 32, false);
exp = tcg_temp_new_i64();
t0 = tcg_temp_new_i64();
- zr = tcg_const_i64(0);
- nan = tcg_const_i64(32767);
+ zr = tcg_constant_i64(0);
+ nan = tcg_constant_i64(32767);
tcg_gen_extract_i64(exp, xbh, 48, 15);
tcg_gen_movi_i64(t0, 0x0001000000000000);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
tcg_gen_deposit_i64(xth, t0, xbh, 0, 48);
- set_cpu_vsrh(rD(ctx->opcode) + 32, xth);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xth, true);
tcg_gen_mov_i64(xtl, xbl);
- set_cpu_vsrl(rD(ctx->opcode) + 32, xtl);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(exp);
- tcg_temp_free_i64(zr);
- tcg_temp_free_i64(nan);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(rD(ctx->opcode) + 32, xtl, false);
}
#endif
@@ -1904,30 +2060,22 @@ static void gen_xviexpsp(DisasContext *ctx)
xal = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xah, xA(ctx->opcode));
- get_cpu_vsrl(xal, xA(ctx->opcode));
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xah, xA(ctx->opcode), true);
+ get_cpu_vsr(xal, xA(ctx->opcode), false);
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
t0 = tcg_temp_new_i64();
tcg_gen_andi_i64(xth, xah, 0x807FFFFF807FFFFF);
tcg_gen_andi_i64(t0, xbh, 0xFF000000FF);
tcg_gen_shli_i64(t0, t0, 23);
tcg_gen_or_i64(xth, xth, t0);
- set_cpu_vsrh(xT(ctx->opcode), xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
tcg_gen_andi_i64(xtl, xal, 0x807FFFFF807FFFFF);
tcg_gen_andi_i64(t0, xbl, 0xFF000000FF);
tcg_gen_shli_i64(t0, t0, 23);
tcg_gen_or_i64(xtl, xtl, t0);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xah);
- tcg_temp_free_i64(xal);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_xviexpdp(DisasContext *ctx)
@@ -1949,23 +2097,16 @@ static void gen_xviexpdp(DisasContext *ctx)
xal = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xah, xA(ctx->opcode));
- get_cpu_vsrl(xal, xA(ctx->opcode));
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xah, xA(ctx->opcode), true);
+ get_cpu_vsr(xal, xA(ctx->opcode), false);
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
tcg_gen_deposit_i64(xth, xah, xbh, 52, 11);
- set_cpu_vsrh(xT(ctx->opcode), xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
tcg_gen_deposit_i64(xtl, xal, xbl, 52, 11);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xah);
- tcg_temp_free_i64(xal);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_xvxexpsp(DisasContext *ctx)
@@ -1983,20 +2124,15 @@ static void gen_xvxexpsp(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
tcg_gen_shri_i64(xth, xbh, 23);
tcg_gen_andi_i64(xth, xth, 0xFF000000FF);
- set_cpu_vsrh(xT(ctx->opcode), xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
tcg_gen_shri_i64(xtl, xbl, 23);
tcg_gen_andi_i64(xtl, xtl, 0xFF000000FF);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
static void gen_xvxexpdp(DisasContext *ctx)
@@ -2014,21 +2150,28 @@ static void gen_xvxexpdp(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
tcg_gen_extract_i64(xth, xbh, 52, 11);
- set_cpu_vsrh(xT(ctx->opcode), xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
tcg_gen_extract_i64(xtl, xbl, 52, 11);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
-
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
}
-GEN_VSX_HELPER_X2(xvxsigsp, 0x00, 0x04, 0, PPC2_ISA300)
+static bool trans_XVXSIGSP(DisasContext *ctx, arg_XX2 *a)
+{
+ TCGv_ptr t, b;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ t = gen_vsr_ptr(a->xt);
+ b = gen_vsr_ptr(a->xb);
+
+ gen_helper_XVXSIGSP(t, b);
+ return true;
+}
static void gen_xvxsigdp(DisasContext *ctx)
{
@@ -2046,37 +2189,722 @@ static void gen_xvxsigdp(DisasContext *ctx)
xtl = tcg_temp_new_i64();
xbh = tcg_temp_new_i64();
xbl = tcg_temp_new_i64();
- get_cpu_vsrh(xbh, xB(ctx->opcode));
- get_cpu_vsrl(xbl, xB(ctx->opcode));
+ get_cpu_vsr(xbh, xB(ctx->opcode), true);
+ get_cpu_vsr(xbl, xB(ctx->opcode), false);
exp = tcg_temp_new_i64();
t0 = tcg_temp_new_i64();
- zr = tcg_const_i64(0);
- nan = tcg_const_i64(2047);
+ zr = tcg_constant_i64(0);
+ nan = tcg_constant_i64(2047);
tcg_gen_extract_i64(exp, xbh, 52, 11);
tcg_gen_movi_i64(t0, 0x0010000000000000);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
tcg_gen_deposit_i64(xth, t0, xbh, 0, 52);
- set_cpu_vsrh(xT(ctx->opcode), xth);
+ set_cpu_vsr(xT(ctx->opcode), xth, true);
tcg_gen_extract_i64(exp, xbl, 52, 11);
tcg_gen_movi_i64(t0, 0x0010000000000000);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, zr, zr, t0);
tcg_gen_movcond_i64(TCG_COND_EQ, t0, exp, nan, zr, t0);
tcg_gen_deposit_i64(xtl, t0, xbl, 0, 52);
- set_cpu_vsrl(xT(ctx->opcode), xtl);
+ set_cpu_vsr(xT(ctx->opcode), xtl, false);
+}
+
+static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
+ int rt, bool store, bool paired)
+{
+ TCGv ea;
+ TCGv_i64 xt;
+ MemOp mop;
+ int rt1, rt2;
+
+ xt = tcg_temp_new_i64();
+
+ mop = DEF_MEMOP(MO_UQ);
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ ea = do_ea_calc(ctx, ra, displ);
+
+ if (paired && ctx->le_mode) {
+ rt1 = rt + 1;
+ rt2 = rt;
+ } else {
+ rt1 = rt;
+ rt2 = rt + 1;
+ }
+
+ if (store) {
+ get_cpu_vsr(xt, rt1, !ctx->le_mode);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ gen_addr_add(ctx, ea, ea, 8);
+ get_cpu_vsr(xt, rt1, ctx->le_mode);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ if (paired) {
+ gen_addr_add(ctx, ea, ea, 8);
+ get_cpu_vsr(xt, rt2, !ctx->le_mode);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ gen_addr_add(ctx, ea, ea, 8);
+ get_cpu_vsr(xt, rt2, ctx->le_mode);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ }
+ } else {
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(rt1, xt, !ctx->le_mode);
+ gen_addr_add(ctx, ea, ea, 8);
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(rt1, xt, ctx->le_mode);
+ if (paired) {
+ gen_addr_add(ctx, ea, ea, 8);
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(rt2, xt, !ctx->le_mode);
+ gen_addr_add(ctx, ea, ea, 8);
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(rt2, xt, ctx->le_mode);
+ }
+ }
+ return true;
+}
+
+static bool do_lstxv_D(DisasContext *ctx, arg_D *a, bool store, bool paired)
+{
+ if (paired || a->rt < 32) {
+ REQUIRE_VSX(ctx);
+ } else {
+ REQUIRE_VECTOR(ctx);
+ }
+
+ return do_lstxv(ctx, a->ra, tcg_constant_tl(a->si), a->rt, store, paired);
+}
+
+static bool do_lstxv_PLS_D(DisasContext *ctx, arg_PLS_D *a,
+ bool store, bool paired)
+{
+ arg_D d;
+ REQUIRE_VSX(ctx);
+
+ if (!resolve_PLS_D(ctx, &d, a)) {
+ return true;
+ }
+
+ return do_lstxv(ctx, d.ra, tcg_constant_tl(d.si), d.rt, store, paired);
+}
+
+static bool do_lstxv_X(DisasContext *ctx, arg_X *a, bool store, bool paired)
+{
+ if (paired || a->rt >= 32) {
+ REQUIRE_VSX(ctx);
+ } else {
+ REQUIRE_VECTOR(ctx);
+ }
+
+ return do_lstxv(ctx, a->ra, cpu_gpr[a->rb], a->rt, store, paired);
+}
+
+static bool do_lstxsd(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
+{
+ TCGv ea;
+ TCGv_i64 xt;
+ MemOp mop;
+
+ if (store) {
+ REQUIRE_VECTOR(ctx);
+ } else {
+ REQUIRE_VSX(ctx);
+ }
+
+ xt = tcg_temp_new_i64();
+ mop = DEF_MEMOP(MO_UQ);
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ ea = do_ea_calc(ctx, ra, displ);
+
+ if (store) {
+ get_cpu_vsr(xt, rt + 32, true);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ } else {
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(rt + 32, xt, true);
+ set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
+ }
+ return true;
+}
+
+static bool do_lstxsd_DS(DisasContext *ctx, arg_D *a, bool store)
+{
+ return do_lstxsd(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
+}
+
+static bool do_plstxsd_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
+{
+ arg_D d;
+
+ if (!resolve_PLS_D(ctx, &d, a)) {
+ return true;
+ }
+
+ return do_lstxsd(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
+}
+
+static bool do_lstxssp(DisasContext *ctx, int rt, int ra, TCGv displ, bool store)
+{
+ TCGv ea;
+ TCGv_i64 xt;
+
+ REQUIRE_VECTOR(ctx);
+
+ xt = tcg_temp_new_i64();
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ ea = do_ea_calc(ctx, ra, displ);
+
+ if (store) {
+ get_cpu_vsr(xt, rt + 32, true);
+ gen_qemu_st32fs(ctx, xt, ea);
+ } else {
+ gen_qemu_ld32fs(ctx, xt, ea);
+ set_cpu_vsr(rt + 32, xt, true);
+ set_cpu_vsr(rt + 32, tcg_constant_i64(0), false);
+ }
+ return true;
+}
+
+static bool do_lstxssp_DS(DisasContext *ctx, arg_D *a, bool store)
+{
+ return do_lstxssp(ctx, a->rt, a->ra, tcg_constant_tl(a->si), store);
+}
+
+static bool do_plstxssp_PLS_D(DisasContext *ctx, arg_PLS_D *a, bool store)
+{
+ arg_D d;
+
+ if (!resolve_PLS_D(ctx, &d, a)) {
+ return true;
+ }
+
+ return do_lstxssp(ctx, d.rt, d.ra, tcg_constant_tl(d.si), store);
+}
+
+TRANS_FLAGS2(ISA300, LXSD, do_lstxsd_DS, false)
+TRANS_FLAGS2(ISA300, STXSD, do_lstxsd_DS, true)
+TRANS_FLAGS2(ISA300, LXSSP, do_lstxssp_DS, false)
+TRANS_FLAGS2(ISA300, STXSSP, do_lstxssp_DS, true)
+TRANS_FLAGS2(ISA300, STXV, do_lstxv_D, true, false)
+TRANS_FLAGS2(ISA300, LXV, do_lstxv_D, false, false)
+TRANS_FLAGS2(ISA310, STXVP, do_lstxv_D, true, true)
+TRANS_FLAGS2(ISA310, LXVP, do_lstxv_D, false, true)
+TRANS_FLAGS2(ISA300, STXVX, do_lstxv_X, true, false)
+TRANS_FLAGS2(ISA300, LXVX, do_lstxv_X, false, false)
+TRANS_FLAGS2(ISA310, STXVPX, do_lstxv_X, true, true)
+TRANS_FLAGS2(ISA310, LXVPX, do_lstxv_X, false, true)
+TRANS64_FLAGS2(ISA310, PLXSD, do_plstxsd_PLS_D, false)
+TRANS64_FLAGS2(ISA310, PSTXSD, do_plstxsd_PLS_D, true)
+TRANS64_FLAGS2(ISA310, PLXSSP, do_plstxssp_PLS_D, false)
+TRANS64_FLAGS2(ISA310, PSTXSSP, do_plstxssp_PLS_D, true)
+TRANS64_FLAGS2(ISA310, PSTXV, do_lstxv_PLS_D, true, false)
+TRANS64_FLAGS2(ISA310, PLXV, do_lstxv_PLS_D, false, false)
+TRANS64_FLAGS2(ISA310, PSTXVP, do_lstxv_PLS_D, true, true)
+TRANS64_FLAGS2(ISA310, PLXVP, do_lstxv_PLS_D, false, true)
+
+static bool do_lstrm(DisasContext *ctx, arg_X *a, MemOp mop, bool store)
+{
+ TCGv ea;
+ TCGv_i64 xt;
+
+ REQUIRE_VSX(ctx);
+
+ xt = tcg_temp_new_i64();
+
+ gen_set_access_type(ctx, ACCESS_INT);
+ ea = do_ea_calc(ctx, a->ra , cpu_gpr[a->rb]);
- tcg_temp_free_i64(t0);
- tcg_temp_free_i64(exp);
- tcg_temp_free_i64(zr);
- tcg_temp_free_i64(nan);
- tcg_temp_free_i64(xth);
- tcg_temp_free_i64(xtl);
- tcg_temp_free_i64(xbh);
- tcg_temp_free_i64(xbl);
+ if (store) {
+ get_cpu_vsr(xt, a->rt, false);
+ tcg_gen_qemu_st_i64(xt, ea, ctx->mem_idx, mop);
+ } else {
+ tcg_gen_qemu_ld_i64(xt, ea, ctx->mem_idx, mop);
+ set_cpu_vsr(a->rt, xt, false);
+ set_cpu_vsr(a->rt, tcg_constant_i64(0), true);
+ }
+ return true;
}
+TRANS_FLAGS2(ISA310, LXVRBX, do_lstrm, DEF_MEMOP(MO_UB), false)
+TRANS_FLAGS2(ISA310, LXVRHX, do_lstrm, DEF_MEMOP(MO_UW), false)
+TRANS_FLAGS2(ISA310, LXVRWX, do_lstrm, DEF_MEMOP(MO_UL), false)
+TRANS_FLAGS2(ISA310, LXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), false)
+TRANS_FLAGS2(ISA310, STXVRBX, do_lstrm, DEF_MEMOP(MO_UB), true)
+TRANS_FLAGS2(ISA310, STXVRHX, do_lstrm, DEF_MEMOP(MO_UW), true)
+TRANS_FLAGS2(ISA310, STXVRWX, do_lstrm, DEF_MEMOP(MO_UL), true)
+TRANS_FLAGS2(ISA310, STXVRDX, do_lstrm, DEF_MEMOP(MO_UQ), true)
+
+static void gen_xxeval_i64(TCGv_i64 t, TCGv_i64 a, TCGv_i64 b, TCGv_i64 c,
+ int64_t imm)
+{
+ /*
+ * Instead of processing imm bit-by-bit, we'll skip the computation of
+ * conjunctions whose corresponding bit is unset.
+ */
+ int bit;
+ TCGv_i64 conj, disj;
+
+ conj = tcg_temp_new_i64();
+ disj = tcg_temp_new_i64();
+ tcg_gen_movi_i64(disj, 0);
+
+ /* Iterate over set bits from the least to the most significant bit */
+ while (imm) {
+ /*
+ * Get the next bit to be processed with ctz64. Invert the result of
+ * ctz64 to match the indexing used by PowerISA.
+ */
+ bit = 7 - ctz64(imm);
+ if (bit & 0x4) {
+ tcg_gen_mov_i64(conj, a);
+ } else {
+ tcg_gen_not_i64(conj, a);
+ }
+ if (bit & 0x2) {
+ tcg_gen_and_i64(conj, conj, b);
+ } else {
+ tcg_gen_andc_i64(conj, conj, b);
+ }
+ if (bit & 0x1) {
+ tcg_gen_and_i64(conj, conj, c);
+ } else {
+ tcg_gen_andc_i64(conj, conj, c);
+ }
+ tcg_gen_or_i64(disj, disj, conj);
+
+ /* Unset the least significant bit that is set */
+ imm &= imm - 1;
+ }
+
+ tcg_gen_mov_i64(t, disj);
+}
+
+static void gen_xxeval_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+ TCGv_vec c, int64_t imm)
+{
+ /*
+ * Instead of processing imm bit-by-bit, we'll skip the computation of
+ * conjunctions whose corresponding bit is unset.
+ */
+ int bit;
+ TCGv_vec disj, conj;
+
+ conj = tcg_temp_new_vec_matching(t);
+ disj = tcg_temp_new_vec_matching(t);
+ tcg_gen_dupi_vec(vece, disj, 0);
+
+ /* Iterate over set bits from the least to the most significant bit */
+ while (imm) {
+ /*
+ * Get the next bit to be processed with ctz64. Invert the result of
+ * ctz64 to match the indexing used by PowerISA.
+ */
+ bit = 7 - ctz64(imm);
+ if (bit & 0x4) {
+ tcg_gen_mov_vec(conj, a);
+ } else {
+ tcg_gen_not_vec(vece, conj, a);
+ }
+ if (bit & 0x2) {
+ tcg_gen_and_vec(vece, conj, conj, b);
+ } else {
+ tcg_gen_andc_vec(vece, conj, conj, b);
+ }
+ if (bit & 0x1) {
+ tcg_gen_and_vec(vece, conj, conj, c);
+ } else {
+ tcg_gen_andc_vec(vece, conj, conj, c);
+ }
+ tcg_gen_or_vec(vece, disj, disj, conj);
+
+ /* Unset the least significant bit that is set */
+ imm &= imm - 1;
+ }
+
+ tcg_gen_mov_vec(t, disj);
+}
+
+static bool trans_XXEVAL(DisasContext *ctx, arg_8RR_XX4_imm *a)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_andc_vec, 0
+ };
+ static const GVecGen4i op = {
+ .fniv = gen_xxeval_vec,
+ .fno = gen_helper_XXEVAL,
+ .fni8 = gen_xxeval_i64,
+ .opt_opc = vecop_list,
+ .vece = MO_64
+ };
+ int xt = vsr_full_offset(a->xt), xa = vsr_full_offset(a->xa),
+ xb = vsr_full_offset(a->xb), xc = vsr_full_offset(a->xc);
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ /* Equivalent functions that can be implemented with a single gen_gvec */
+ switch (a->imm) {
+ case 0b00000000: /* false */
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(0), false);
+ break;
+ case 0b00000011: /* and(B,A) */
+ tcg_gen_gvec_and(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b00000101: /* and(C,A) */
+ tcg_gen_gvec_and(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b00001111: /* A */
+ tcg_gen_gvec_mov(MO_64, xt, xa, 16, 16);
+ break;
+ case 0b00010001: /* and(C,B) */
+ tcg_gen_gvec_and(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b00011011: /* C?B:A */
+ tcg_gen_gvec_bitsel(MO_64, xt, xc, xb, xa, 16, 16);
+ break;
+ case 0b00011101: /* B?C:A */
+ tcg_gen_gvec_bitsel(MO_64, xt, xb, xc, xa, 16, 16);
+ break;
+ case 0b00100111: /* C?A:B */
+ tcg_gen_gvec_bitsel(MO_64, xt, xc, xa, xb, 16, 16);
+ break;
+ case 0b00110011: /* B */
+ tcg_gen_gvec_mov(MO_64, xt, xb, 16, 16);
+ break;
+ case 0b00110101: /* A?C:B */
+ tcg_gen_gvec_bitsel(MO_64, xt, xa, xc, xb, 16, 16);
+ break;
+ case 0b00111100: /* xor(B,A) */
+ tcg_gen_gvec_xor(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b00111111: /* or(B,A) */
+ tcg_gen_gvec_or(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b01000111: /* B?A:C */
+ tcg_gen_gvec_bitsel(MO_64, xt, xb, xa, xc, 16, 16);
+ break;
+ case 0b01010011: /* A?B:C */
+ tcg_gen_gvec_bitsel(MO_64, xt, xa, xb, xc, 16, 16);
+ break;
+ case 0b01010101: /* C */
+ tcg_gen_gvec_mov(MO_64, xt, xc, 16, 16);
+ break;
+ case 0b01011010: /* xor(C,A) */
+ tcg_gen_gvec_xor(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b01011111: /* or(C,A) */
+ tcg_gen_gvec_or(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b01100110: /* xor(C,B) */
+ tcg_gen_gvec_xor(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b01110111: /* or(C,B) */
+ tcg_gen_gvec_or(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b10001000: /* nor(C,B) */
+ tcg_gen_gvec_nor(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b10011001: /* eqv(C,B) */
+ tcg_gen_gvec_eqv(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b10100000: /* nor(C,A) */
+ tcg_gen_gvec_nor(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b10100101: /* eqv(C,A) */
+ tcg_gen_gvec_eqv(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b10101010: /* not(C) */
+ tcg_gen_gvec_not(MO_64, xt, xc, 16, 16);
+ break;
+ case 0b11000000: /* nor(B,A) */
+ tcg_gen_gvec_nor(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b11000011: /* eqv(B,A) */
+ tcg_gen_gvec_eqv(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b11001100: /* not(B) */
+ tcg_gen_gvec_not(MO_64, xt, xb, 16, 16);
+ break;
+ case 0b11101110: /* nand(C,B) */
+ tcg_gen_gvec_nand(MO_64, xt, xc, xb, 16, 16);
+ break;
+ case 0b11110000: /* not(A) */
+ tcg_gen_gvec_not(MO_64, xt, xa, 16, 16);
+ break;
+ case 0b11111010: /* nand(C,A) */
+ tcg_gen_gvec_nand(MO_64, xt, xc, xa, 16, 16);
+ break;
+ case 0b11111100: /* nand(B,A) */
+ tcg_gen_gvec_nand(MO_64, xt, xb, xa, 16, 16);
+ break;
+ case 0b11111111: /* true */
+ set_cpu_vsr(a->xt, tcg_constant_i64(-1), true);
+ set_cpu_vsr(a->xt, tcg_constant_i64(-1), false);
+ break;
+ default:
+ /* Fallback to compute all conjunctions/disjunctions */
+ tcg_gen_gvec_4i(xt, xa, xb, xc, 16, 16, a->imm, &op);
+ }
+
+ return true;
+}
+
+static void gen_xxblendv_vec(unsigned vece, TCGv_vec t, TCGv_vec a, TCGv_vec b,
+ TCGv_vec c)
+{
+ TCGv_vec tmp = tcg_temp_new_vec_matching(c);
+ tcg_gen_sari_vec(vece, tmp, c, (8 << vece) - 1);
+ tcg_gen_bitsel_vec(vece, t, tmp, b, a);
+}
+
+static bool do_xxblendv(DisasContext *ctx, arg_8RR_XX4 *a, unsigned vece)
+{
+ static const TCGOpcode vecop_list[] = {
+ INDEX_op_sari_vec, 0
+ };
+ static const GVecGen4 ops[4] = {
+ {
+ .fniv = gen_xxblendv_vec,
+ .fno = gen_helper_XXBLENDVB,
+ .opt_opc = vecop_list,
+ .vece = MO_8
+ },
+ {
+ .fniv = gen_xxblendv_vec,
+ .fno = gen_helper_XXBLENDVH,
+ .opt_opc = vecop_list,
+ .vece = MO_16
+ },
+ {
+ .fniv = gen_xxblendv_vec,
+ .fno = gen_helper_XXBLENDVW,
+ .opt_opc = vecop_list,
+ .vece = MO_32
+ },
+ {
+ .fniv = gen_xxblendv_vec,
+ .fno = gen_helper_XXBLENDVD,
+ .opt_opc = vecop_list,
+ .vece = MO_64
+ }
+ };
+
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_4(vsr_full_offset(a->xt), vsr_full_offset(a->xa),
+ vsr_full_offset(a->xb), vsr_full_offset(a->xc),
+ 16, 16, &ops[vece]);
+
+ return true;
+}
+
+TRANS(XXBLENDVB, do_xxblendv, MO_8)
+TRANS(XXBLENDVH, do_xxblendv, MO_16)
+TRANS(XXBLENDVW, do_xxblendv, MO_32)
+TRANS(XXBLENDVD, do_xxblendv, MO_64)
+
+static bool do_helper_XX3(DisasContext *ctx, arg_XX3 *a,
+ void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr xt, xa, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_vsr_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+
+ helper(tcg_env, xt, xa, xb);
+ return true;
+}
+
+TRANS(XSCMPEQDP, do_helper_XX3, gen_helper_XSCMPEQDP)
+TRANS(XSCMPGEDP, do_helper_XX3, gen_helper_XSCMPGEDP)
+TRANS(XSCMPGTDP, do_helper_XX3, gen_helper_XSCMPGTDP)
+TRANS(XSMAXCDP, do_helper_XX3, gen_helper_XSMAXCDP)
+TRANS(XSMINCDP, do_helper_XX3, gen_helper_XSMINCDP)
+TRANS(XSMAXJDP, do_helper_XX3, gen_helper_XSMAXJDP)
+TRANS(XSMINJDP, do_helper_XX3, gen_helper_XSMINJDP)
+
+static bool do_helper_X(arg_X *a,
+ void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ TCGv_ptr rt, ra, rb;
+
+ rt = gen_avr_ptr(a->rt);
+ ra = gen_avr_ptr(a->ra);
+ rb = gen_avr_ptr(a->rb);
+
+ helper(tcg_env, rt, ra, rb);
+ return true;
+}
+
+static bool do_xscmpqp(DisasContext *ctx, arg_X *a,
+ void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ return do_helper_X(a, helper);
+}
+
+TRANS(XSCMPEQQP, do_xscmpqp, gen_helper_XSCMPEQQP)
+TRANS(XSCMPGEQP, do_xscmpqp, gen_helper_XSCMPGEQP)
+TRANS(XSCMPGTQP, do_xscmpqp, gen_helper_XSCMPGTQP)
+TRANS(XSMAXCQP, do_xscmpqp, gen_helper_XSMAXCQP)
+TRANS(XSMINCQP, do_xscmpqp, gen_helper_XSMINCQP)
+
+static bool trans_XVCVSPBF16(DisasContext *ctx, arg_XX2 *a)
+{
+ TCGv_ptr xt, xb;
+
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ xt = gen_vsr_ptr(a->xt);
+ xb = gen_vsr_ptr(a->xb);
+
+ gen_helper_XVCVSPBF16(tcg_env, xt, xb);
+ return true;
+}
+
+static bool trans_XVCVBF16SPN(DisasContext *ctx, arg_XX2 *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+
+ tcg_gen_gvec_shli(MO_32, vsr_full_offset(a->xt), vsr_full_offset(a->xb),
+ 16, 16, 16);
+
+ return true;
+}
+
+ /*
+ * The PowerISA 3.1 mentions that for the current version of the
+ * architecture, "the hardware implementation provides the effect of
+ * ACC[i] and VSRs 4*i to 4*i + 3 logically containing the same data"
+ * and "The Accumulators introduce no new logical state at this time"
+ * (page 501). For now it seems unnecessary to create new structures,
+ * so ACC[i] is the same as VSRs 4*i to 4*i+3 and therefore
+ * move to and from accumulators are no-ops.
+ */
+static bool trans_XXMFACC(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ return true;
+}
+
+static bool trans_XXMTACC(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ return true;
+}
+
+static bool trans_XXSETACCZ(DisasContext *ctx, arg_X_a *a)
+{
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ tcg_gen_gvec_dup_imm(MO_64, acc_full_offset(a->ra), 64, 64, 0);
+ return true;
+}
+
+static bool do_ger(DisasContext *ctx, arg_MMIRR_XX3 *a,
+ void (*helper)(TCGv_env, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32))
+{
+ uint32_t mask;
+ TCGv_ptr xt, xa, xb;
+ REQUIRE_INSNS_FLAGS2(ctx, ISA310);
+ REQUIRE_VSX(ctx);
+ if (unlikely((a->xa / 4 == a->xt) || (a->xb / 4 == a->xt))) {
+ gen_invalid(ctx);
+ return true;
+ }
+
+ xt = gen_acc_ptr(a->xt);
+ xa = gen_vsr_ptr(a->xa);
+ xb = gen_vsr_ptr(a->xb);
+
+ mask = ger_pack_masks(a->pmsk, a->ymsk, a->xmsk);
+ helper(tcg_env, xa, xb, xt, tcg_constant_i32(mask));
+ return true;
+}
+
+TRANS(XVI4GER8, do_ger, gen_helper_XVI4GER8)
+TRANS(XVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
+TRANS(XVI8GER4, do_ger, gen_helper_XVI8GER4)
+TRANS(XVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
+TRANS(XVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
+TRANS(XVI16GER2, do_ger, gen_helper_XVI16GER2)
+TRANS(XVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
+TRANS(XVI16GER2S, do_ger, gen_helper_XVI16GER2S)
+TRANS(XVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
+
+TRANS64(PMXVI4GER8, do_ger, gen_helper_XVI4GER8)
+TRANS64(PMXVI4GER8PP, do_ger, gen_helper_XVI4GER8PP)
+TRANS64(PMXVI8GER4, do_ger, gen_helper_XVI8GER4)
+TRANS64(PMXVI8GER4PP, do_ger, gen_helper_XVI8GER4PP)
+TRANS64(PMXVI8GER4SPP, do_ger, gen_helper_XVI8GER4SPP)
+TRANS64(PMXVI16GER2, do_ger, gen_helper_XVI16GER2)
+TRANS64(PMXVI16GER2PP, do_ger, gen_helper_XVI16GER2PP)
+TRANS64(PMXVI16GER2S, do_ger, gen_helper_XVI16GER2S)
+TRANS64(PMXVI16GER2SPP, do_ger, gen_helper_XVI16GER2SPP)
+
+TRANS(XVBF16GER2, do_ger, gen_helper_XVBF16GER2)
+TRANS(XVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
+TRANS(XVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
+TRANS(XVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
+TRANS(XVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
+
+TRANS(XVF16GER2, do_ger, gen_helper_XVF16GER2)
+TRANS(XVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
+TRANS(XVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
+TRANS(XVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
+TRANS(XVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
+
+TRANS(XVF32GER, do_ger, gen_helper_XVF32GER)
+TRANS(XVF32GERPP, do_ger, gen_helper_XVF32GERPP)
+TRANS(XVF32GERPN, do_ger, gen_helper_XVF32GERPN)
+TRANS(XVF32GERNP, do_ger, gen_helper_XVF32GERNP)
+TRANS(XVF32GERNN, do_ger, gen_helper_XVF32GERNN)
+
+TRANS(XVF64GER, do_ger, gen_helper_XVF64GER)
+TRANS(XVF64GERPP, do_ger, gen_helper_XVF64GERPP)
+TRANS(XVF64GERPN, do_ger, gen_helper_XVF64GERPN)
+TRANS(XVF64GERNP, do_ger, gen_helper_XVF64GERNP)
+TRANS(XVF64GERNN, do_ger, gen_helper_XVF64GERNN)
+
+TRANS64(PMXVBF16GER2, do_ger, gen_helper_XVBF16GER2)
+TRANS64(PMXVBF16GER2PP, do_ger, gen_helper_XVBF16GER2PP)
+TRANS64(PMXVBF16GER2PN, do_ger, gen_helper_XVBF16GER2PN)
+TRANS64(PMXVBF16GER2NP, do_ger, gen_helper_XVBF16GER2NP)
+TRANS64(PMXVBF16GER2NN, do_ger, gen_helper_XVBF16GER2NN)
+
+TRANS64(PMXVF16GER2, do_ger, gen_helper_XVF16GER2)
+TRANS64(PMXVF16GER2PP, do_ger, gen_helper_XVF16GER2PP)
+TRANS64(PMXVF16GER2PN, do_ger, gen_helper_XVF16GER2PN)
+TRANS64(PMXVF16GER2NP, do_ger, gen_helper_XVF16GER2NP)
+TRANS64(PMXVF16GER2NN, do_ger, gen_helper_XVF16GER2NN)
+
+TRANS64(PMXVF32GER, do_ger, gen_helper_XVF32GER)
+TRANS64(PMXVF32GERPP, do_ger, gen_helper_XVF32GERPP)
+TRANS64(PMXVF32GERPN, do_ger, gen_helper_XVF32GERPN)
+TRANS64(PMXVF32GERNP, do_ger, gen_helper_XVF32GERNP)
+TRANS64(PMXVF32GERNN, do_ger, gen_helper_XVF32GERNN)
+
+TRANS64(PMXVF64GER, do_ger, gen_helper_XVF64GER)
+TRANS64(PMXVF64GERPP, do_ger, gen_helper_XVF64GERPP)
+TRANS64(PMXVF64GERPN, do_ger, gen_helper_XVF64GERPN)
+TRANS64(PMXVF64GERNP, do_ger, gen_helper_XVF64GERNP)
+TRANS64(PMXVF64GERNN, do_ger, gen_helper_XVF64GERNN)
+
#undef GEN_XX2FORM
#undef GEN_XX3FORM
#undef GEN_XX2IFORM
diff --git a/target/ppc/translate/vsx-ops.c.inc b/target/ppc/translate/vsx-ops.c.inc
index 1d41beef26..a3ba094d62 100644
--- a/target/ppc/translate/vsx-ops.c.inc
+++ b/target/ppc/translate/vsx-ops.c.inc
@@ -10,7 +10,6 @@ GEN_HANDLER_E(lxvdsx, 0x1F, 0x0C, 0x0A, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvw4x, 0x1F, 0x0C, 0x18, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(lxvh8x, 0x1F, 0x0C, 0x19, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(lxvb16x, 0x1F, 0x0C, 0x1B, 0, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E(lxvx, 0x1F, 0x0C, 0x08, 0x00000040, PPC_NONE, PPC2_ISA300),
#if defined(TARGET_PPC64)
GEN_HANDLER_E(lxvl, 0x1F, 0x0D, 0x08, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(lxvll, 0x1F, 0x0D, 0x09, 0, PPC_NONE, PPC2_ISA300),
@@ -25,7 +24,6 @@ GEN_HANDLER_E(stxvd2x, 0x1F, 0xC, 0x1E, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxvw4x, 0x1F, 0xC, 0x1C, 0, PPC_NONE, PPC2_VSX),
GEN_HANDLER_E(stxvh8x, 0x1F, 0x0C, 0x1D, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(stxvb16x, 0x1F, 0x0C, 0x1F, 0, PPC_NONE, PPC2_ISA300),
-GEN_HANDLER_E(stxvx, 0x1F, 0x0C, 0x0C, 0, PPC_NONE, PPC2_ISA300),
#if defined(TARGET_PPC64)
GEN_HANDLER_E(stxvl, 0x1F, 0x0D, 0x0C, 0, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(stxvll, 0x1F, 0x0D, 0x0D, 0, PPC_NONE, PPC2_ISA300),
@@ -135,7 +133,6 @@ GEN_VSX_XFORM_300_EO(xsnabsqp, 0x04, 0x19, 0x08, 0x00000001),
GEN_VSX_XFORM_300_EO(xsnegqp, 0x04, 0x19, 0x10, 0x00000001),
GEN_VSX_XFORM_300(xscpsgnqp, 0x04, 0x03, 0x00000001),
GEN_VSX_XFORM_300_EO(xscvdpqp, 0x04, 0x1A, 0x16, 0x00000001),
-GEN_VSX_XFORM_300_EO(xscvqpdp, 0x04, 0x1A, 0x14, 0x0),
GEN_VSX_XFORM_300_EO(xscvqpsdz, 0x04, 0x1A, 0x19, 0x00000001),
GEN_VSX_XFORM_300_EO(xscvqpswz, 0x04, 0x1A, 0x09, 0x00000001),
GEN_VSX_XFORM_300_EO(xscvqpudz, 0x04, 0x1A, 0x11, 0x00000001),
@@ -150,33 +147,11 @@ GEN_HANDLER_E(xsiexpdp, 0x3C, 0x16, 0x1C, 0, PPC_NONE, PPC2_ISA300),
GEN_VSX_XFORM_300(xsiexpqp, 0x4, 0x1B, 0x00000001),
#endif
-GEN_XX2FORM(xststdcdp, 0x14, 0x16, PPC2_ISA300),
-GEN_XX2FORM(xststdcsp, 0x14, 0x12, PPC2_ISA300),
-GEN_VSX_XFORM_300(xststdcqp, 0x04, 0x16, 0x00000001),
-
GEN_XX3FORM(xviexpsp, 0x00, 0x1B, PPC2_ISA300),
GEN_XX3FORM(xviexpdp, 0x00, 0x1F, PPC2_ISA300),
GEN_XX2FORM_EO(xvxexpdp, 0x16, 0x1D, 0x00, PPC2_ISA300),
GEN_XX2FORM_EO(xvxsigdp, 0x16, 0x1D, 0x01, PPC2_ISA300),
GEN_XX2FORM_EO(xvxexpsp, 0x16, 0x1D, 0x08, PPC2_ISA300),
-GEN_XX2FORM_EO(xvxsigsp, 0x16, 0x1D, 0x09, PPC2_ISA300),
-
-/* DCMX = bit[25] << 6 | bit[29] << 5 | bit[11:15] */
-#define GEN_XX2FORM_DCMX(name, opc2, opc3, fl2) \
-GEN_XX3FORM(name, opc2, opc3 | 0, fl2), \
-GEN_XX3FORM(name, opc2, opc3 | 1, fl2)
-
-GEN_XX2FORM_DCMX(xvtstdcdp, 0x14, 0x1E, PPC2_ISA300),
-GEN_XX2FORM_DCMX(xvtstdcsp, 0x14, 0x1A, PPC2_ISA300),
-
-GEN_XX2FORM(xvabsdp, 0x12, 0x1D, PPC2_VSX),
-GEN_XX2FORM(xvnabsdp, 0x12, 0x1E, PPC2_VSX),
-GEN_XX2FORM(xvnegdp, 0x12, 0x1F, PPC2_VSX),
-GEN_XX3FORM(xvcpsgndp, 0x00, 0x1E, PPC2_VSX),
-GEN_XX2FORM(xvabssp, 0x12, 0x19, PPC2_VSX),
-GEN_XX2FORM(xvnabssp, 0x12, 0x1A, PPC2_VSX),
-GEN_XX2FORM(xvnegsp, 0x12, 0x1B, PPC2_VSX),
-GEN_XX3FORM(xvcpsgnsp, 0x00, 0x1A, PPC2_VSX),
GEN_XX3FORM(xsadddp, 0x00, 0x04, PPC2_VSX),
GEN_VSX_XFORM_300(xsaddqp, 0x04, 0x00, 0x0),
@@ -189,18 +164,6 @@ GEN_XX2FORM(xssqrtdp, 0x16, 0x04, PPC2_VSX),
GEN_XX2FORM(xsrsqrtedp, 0x14, 0x04, PPC2_VSX),
GEN_XX3FORM(xstdivdp, 0x14, 0x07, PPC2_VSX),
GEN_XX2FORM(xstsqrtdp, 0x14, 0x06, PPC2_VSX),
-GEN_XX3FORM_NAME(xsmadddp, "xsmaddadp", 0x04, 0x04, PPC2_VSX),
-GEN_XX3FORM_NAME(xsmadddp, "xsmaddmdp", 0x04, 0x05, PPC2_VSX),
-GEN_XX3FORM_NAME(xsmsubdp, "xsmsubadp", 0x04, 0x06, PPC2_VSX),
-GEN_XX3FORM_NAME(xsmsubdp, "xsmsubmdp", 0x04, 0x07, PPC2_VSX),
-GEN_XX3FORM_NAME(xsnmadddp, "xsnmaddadp", 0x04, 0x14, PPC2_VSX),
-GEN_XX3FORM_NAME(xsnmadddp, "xsnmaddmdp", 0x04, 0x15, PPC2_VSX),
-GEN_XX3FORM_NAME(xsnmsubdp, "xsnmsubadp", 0x04, 0x16, PPC2_VSX),
-GEN_XX3FORM_NAME(xsnmsubdp, "xsnmsubmdp", 0x04, 0x17, PPC2_VSX),
-GEN_XX3FORM(xscmpeqdp, 0x0C, 0x00, PPC2_ISA300),
-GEN_XX3FORM(xscmpgtdp, 0x0C, 0x01, PPC2_ISA300),
-GEN_XX3FORM(xscmpgedp, 0x0C, 0x02, PPC2_ISA300),
-GEN_XX3FORM(xscmpnedp, 0x0C, 0x03, PPC2_ISA300),
GEN_XX3FORM(xscmpexpdp, 0x0C, 0x07, PPC2_ISA300),
GEN_VSX_XFORM_300(xscmpexpqp, 0x04, 0x05, 0x00600001),
GEN_XX2IFORM(xscmpodp, 0x0C, 0x05, PPC2_VSX),
@@ -209,17 +172,12 @@ GEN_VSX_XFORM_300(xscmpoqp, 0x04, 0x04, 0x00600001),
GEN_VSX_XFORM_300(xscmpuqp, 0x04, 0x14, 0x00600001),
GEN_XX3FORM(xsmaxdp, 0x00, 0x14, PPC2_VSX),
GEN_XX3FORM(xsmindp, 0x00, 0x15, PPC2_VSX),
-GEN_XX3FORM(xsmaxcdp, 0x00, 0x10, PPC2_ISA300),
-GEN_XX3FORM(xsmincdp, 0x00, 0x11, PPC2_ISA300),
-GEN_XX3FORM(xsmaxjdp, 0x00, 0x12, PPC2_ISA300),
-GEN_XX3FORM(xsminjdp, 0x00, 0x13, PPC2_ISA300),
GEN_XX2FORM_EO(xscvdphp, 0x16, 0x15, 0x11, PPC2_ISA300),
GEN_XX2FORM(xscvdpsp, 0x12, 0x10, PPC2_VSX),
GEN_XX2FORM(xscvdpspn, 0x16, 0x10, PPC2_VSX207),
GEN_XX2FORM_EO(xscvhpdp, 0x16, 0x15, 0x10, PPC2_ISA300),
GEN_VSX_XFORM_300_EO(xscvsdqp, 0x04, 0x1A, 0x0A, 0x00000001),
GEN_XX2FORM(xscvspdp, 0x12, 0x14, PPC2_VSX),
-GEN_XX2FORM(xscvspdpn, 0x16, 0x14, PPC2_VSX207),
GEN_XX2FORM(xscvdpsxds, 0x10, 0x15, PPC2_VSX),
GEN_XX2FORM(xscvdpsxws, 0x10, 0x05, PPC2_VSX),
GEN_XX2FORM(xscvdpuxds, 0x10, 0x14, PPC2_VSX),
@@ -242,14 +200,6 @@ GEN_XX2FORM(xsresp, 0x14, 0x01, PPC2_VSX207),
GEN_XX2FORM(xsrsp, 0x12, 0x11, PPC2_VSX207),
GEN_XX2FORM(xssqrtsp, 0x16, 0x00, PPC2_VSX207),
GEN_XX2FORM(xsrsqrtesp, 0x14, 0x00, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsmaddsp, "xsmaddasp", 0x04, 0x00, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsmaddsp, "xsmaddmsp", 0x04, 0x01, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsmsubsp, "xsmsubasp", 0x04, 0x02, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsmsubsp, "xsmsubmsp", 0x04, 0x03, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsnmaddsp, "xsnmaddasp", 0x04, 0x10, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsnmaddsp, "xsnmaddmsp", 0x04, 0x11, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsnmsubsp, "xsnmsubasp", 0x04, 0x12, PPC2_VSX207),
-GEN_XX3FORM_NAME(xsnmsubsp, "xsnmsubmsp", 0x04, 0x13, PPC2_VSX207),
GEN_XX2FORM(xscvsxdsp, 0x10, 0x13, PPC2_VSX207),
GEN_XX2FORM(xscvuxdsp, 0x10, 0x12, PPC2_VSX207),
@@ -348,55 +298,4 @@ VSX_LOGICAL(xxlnand, 0x8, 0x16, PPC2_VSX207),
VSX_LOGICAL(xxlorc, 0x8, 0x15, PPC2_VSX207),
GEN_XX3FORM(xxmrghw, 0x08, 0x02, PPC2_VSX),
GEN_XX3FORM(xxmrglw, 0x08, 0x06, PPC2_VSX),
-GEN_XX3FORM(xxperm, 0x08, 0x03, PPC2_ISA300),
-GEN_XX3FORM(xxpermr, 0x08, 0x07, PPC2_ISA300),
-GEN_XX2FORM(xxspltw, 0x08, 0x0A, PPC2_VSX),
-GEN_XX1FORM(xxspltib, 0x08, 0x0B, PPC2_ISA300),
GEN_XX3FORM_DM(xxsldwi, 0x08, 0x00),
-GEN_XX2FORM_EXT(xxextractuw, 0x0A, 0x0A, PPC2_ISA300),
-GEN_XX2FORM_EXT(xxinsertw, 0x0A, 0x0B, PPC2_ISA300),
-
-#define GEN_XXSEL_ROW(opc3) \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x18, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x19, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1A, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1B, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1C, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1D, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1E, opc3, 0, PPC_NONE, PPC2_VSX), \
-GEN_HANDLER2_E(xxsel, "xxsel", 0x3C, 0x1F, opc3, 0, PPC_NONE, PPC2_VSX), \
-
-GEN_XXSEL_ROW(0x00)
-GEN_XXSEL_ROW(0x01)
-GEN_XXSEL_ROW(0x02)
-GEN_XXSEL_ROW(0x03)
-GEN_XXSEL_ROW(0x04)
-GEN_XXSEL_ROW(0x05)
-GEN_XXSEL_ROW(0x06)
-GEN_XXSEL_ROW(0x07)
-GEN_XXSEL_ROW(0x08)
-GEN_XXSEL_ROW(0x09)
-GEN_XXSEL_ROW(0x0A)
-GEN_XXSEL_ROW(0x0B)
-GEN_XXSEL_ROW(0x0C)
-GEN_XXSEL_ROW(0x0D)
-GEN_XXSEL_ROW(0x0E)
-GEN_XXSEL_ROW(0x0F)
-GEN_XXSEL_ROW(0x10)
-GEN_XXSEL_ROW(0x11)
-GEN_XXSEL_ROW(0x12)
-GEN_XXSEL_ROW(0x13)
-GEN_XXSEL_ROW(0x14)
-GEN_XXSEL_ROW(0x15)
-GEN_XXSEL_ROW(0x16)
-GEN_XXSEL_ROW(0x17)
-GEN_XXSEL_ROW(0x18)
-GEN_XXSEL_ROW(0x19)
-GEN_XXSEL_ROW(0x1A)
-GEN_XXSEL_ROW(0x1B)
-GEN_XXSEL_ROW(0x1C)
-GEN_XXSEL_ROW(0x1D)
-GEN_XXSEL_ROW(0x1E)
-GEN_XXSEL_ROW(0x1F)
-
-GEN_XX3FORM_DM(xxpermdi, 0x08, 0x01),