|
@@ -10,6 +10,16 @@ static inline void set_cpu_vsr(int n, TCGv_i64 src, bool high)
|
|
tcg_gen_st_i64(src, tcg_env, vsr64_offset(n, high));
|
|
tcg_gen_st_i64(src, tcg_env, vsr64_offset(n, high));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static inline void get_vsr_full(TCGv_i128 dst, int reg)
|
|
|
|
+{
|
|
|
|
+ tcg_gen_ld_i128(dst, tcg_env, vsr_full_offset(reg));
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static inline void set_vsr_full(int reg, TCGv_i128 src)
|
|
|
|
+{
|
|
|
|
+ tcg_gen_st_i128(src, tcg_env, vsr_full_offset(reg));
|
|
|
|
+}
|
|
|
|
+
|
|
static inline TCGv_ptr gen_vsr_ptr(int reg)
|
|
static inline TCGv_ptr gen_vsr_ptr(int reg)
|
|
{
|
|
{
|
|
TCGv_ptr r = tcg_temp_new_ptr();
|
|
TCGv_ptr r = tcg_temp_new_ptr();
|
|
@@ -24,66 +34,59 @@ static inline TCGv_ptr gen_acc_ptr(int reg)
|
|
return r;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
-#define VSX_LOAD_SCALAR(name, operation) \
|
|
|
|
-static void gen_##name(DisasContext *ctx) \
|
|
|
|
-{ \
|
|
|
|
- TCGv EA; \
|
|
|
|
- TCGv_i64 t0; \
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) { \
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
|
|
|
|
- return; \
|
|
|
|
- } \
|
|
|
|
- t0 = tcg_temp_new_i64(); \
|
|
|
|
- gen_set_access_type(ctx, ACCESS_INT); \
|
|
|
|
- EA = tcg_temp_new(); \
|
|
|
|
- gen_addr_reg_index(ctx, EA); \
|
|
|
|
- gen_qemu_##operation(ctx, t0, EA); \
|
|
|
|
- set_cpu_vsr(xT(ctx->opcode), t0, true); \
|
|
|
|
- /* NOTE: cpu_vsrl is undefined */ \
|
|
|
|
|
|
+static bool do_lxs(DisasContext *ctx, arg_X *a,
|
|
|
|
+ void (*op)(DisasContext *, TCGv_i64, TCGv))
|
|
|
|
+{
|
|
|
|
+ TCGv EA;
|
|
|
|
+ TCGv_i64 t0;
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ t0 = tcg_temp_new_i64();
|
|
|
|
+ gen_set_access_type(ctx, ACCESS_INT);
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
|
|
+ op(ctx, t0, EA);
|
|
|
|
+ set_cpu_vsr(a->rt, t0, true);
|
|
|
|
+ /* NOTE: cpu_vsrl is undefined */
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-VSX_LOAD_SCALAR(lxsdx, ld64_i64)
|
|
|
|
-VSX_LOAD_SCALAR(lxsiwax, ld32s_i64)
|
|
|
|
-VSX_LOAD_SCALAR(lxsibzx, ld8u_i64)
|
|
|
|
-VSX_LOAD_SCALAR(lxsihzx, ld16u_i64)
|
|
|
|
-VSX_LOAD_SCALAR(lxsiwzx, ld32u_i64)
|
|
|
|
-VSX_LOAD_SCALAR(lxsspx, ld32fs)
|
|
|
|
|
|
+TRANS_FLAGS2(VSX, LXSDX, do_lxs, gen_qemu_ld64_i64);
|
|
|
|
+TRANS_FLAGS2(VSX207, LXSIWAX, do_lxs, gen_qemu_ld32s_i64);
|
|
|
|
+TRANS_FLAGS2(ISA300, LXSIBZX, do_lxs, gen_qemu_ld8u_i64);
|
|
|
|
+TRANS_FLAGS2(ISA300, LXSIHZX, do_lxs, gen_qemu_ld16u_i64);
|
|
|
|
+TRANS_FLAGS2(VSX207, LXSIWZX, do_lxs, gen_qemu_ld32u_i64);
|
|
|
|
+TRANS_FLAGS2(VSX207, LXSSPX, do_lxs, gen_qemu_ld32fs);
|
|
|
|
|
|
-static void gen_lxvd2x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVD2X(DisasContext *ctx, arg_LXVD2X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
TCGv_i64 t0;
|
|
TCGv_i64 t0;
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
|
|
|
|
+
|
|
t0 = tcg_temp_new_i64();
|
|
t0 = tcg_temp_new_i64();
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
gen_qemu_ld64_i64(ctx, t0, EA);
|
|
gen_qemu_ld64_i64(ctx, t0, EA);
|
|
- set_cpu_vsr(xT(ctx->opcode), t0, true);
|
|
|
|
|
|
+ set_cpu_vsr(a->rt, t0, true);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
gen_qemu_ld64_i64(ctx, t0, EA);
|
|
gen_qemu_ld64_i64(ctx, t0, EA);
|
|
- set_cpu_vsr(xT(ctx->opcode), t0, false);
|
|
|
|
|
|
+ set_cpu_vsr(a->rt, t0, false);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_lxvw4x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVW4X(DisasContext *ctx, arg_LXVW4X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xth;
|
|
|
|
- TCGv_i64 xtl;
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ TCGv_i64 xth, xtl;
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
|
|
|
|
+
|
|
xth = tcg_temp_new_i64();
|
|
xth = tcg_temp_new_i64();
|
|
xtl = tcg_temp_new_i64();
|
|
xtl = tcg_temp_new_i64();
|
|
-
|
|
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
-
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
if (ctx->le_mode) {
|
|
if (ctx->le_mode) {
|
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
@@ -100,55 +103,45 @@ static void gen_lxvw4x(DisasContext *ctx)
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
|
|
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);
|
|
|
|
|
|
+ set_cpu_vsr(a->rt, xth, true);
|
|
|
|
+ set_cpu_vsr(a->rt, xtl, false);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_lxvwsx(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVWSX(DisasContext *ctx, arg_LXVWSX *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
TCGv_i32 data;
|
|
TCGv_i32 data;
|
|
|
|
|
|
- if (xT(ctx->opcode) < 32) {
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ if (a->rt < 32) {
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
} else {
|
|
} else {
|
|
- if (unlikely(!ctx->altivec_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VPU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ REQUIRE_VECTOR(ctx);
|
|
}
|
|
}
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
-
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
-
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
data = tcg_temp_new_i32();
|
|
data = tcg_temp_new_i32();
|
|
tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
|
|
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_gen_gvec_dup_i32(MO_UL, vsr_full_offset(a->rt), 16, 16, data);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_lxvdsx(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVDSX(DisasContext *ctx, arg_LXVDSX *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
TCGv_i64 data;
|
|
TCGv_i64 data;
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
|
|
|
|
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
-
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
-
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
data = tcg_temp_new_i64();
|
|
data = tcg_temp_new_i64();
|
|
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UQ));
|
|
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);
|
|
|
|
|
|
+ tcg_gen_gvec_dup_i64(MO_UQ, vsr_full_offset(a->rt), 16, 16, data);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
|
|
static void gen_bswap16x8(TCGv_i64 outh, TCGv_i64 outl,
|
|
@@ -187,145 +180,166 @@ static void gen_bswap32x4(TCGv_i64 outh, TCGv_i64 outl,
|
|
tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
|
|
tcg_gen_deposit_i64(outl, outl, lo, 32, 32);
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_lxvh8x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVH8X(DisasContext *ctx, arg_LXVH8X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xth;
|
|
|
|
- TCGv_i64 xtl;
|
|
|
|
|
|
+ TCGv_i64 xth, xtl;
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
xth = tcg_temp_new_i64();
|
|
xth = tcg_temp_new_i64();
|
|
xtl = tcg_temp_new_i64();
|
|
xtl = tcg_temp_new_i64();
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
-
|
|
|
|
- EA = tcg_temp_new();
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
|
|
tcg_gen_qemu_ld_i64(xth, EA, ctx->mem_idx, MO_BEUQ);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
|
|
tcg_gen_qemu_ld_i64(xtl, EA, ctx->mem_idx, MO_BEUQ);
|
|
if (ctx->le_mode) {
|
|
if (ctx->le_mode) {
|
|
gen_bswap16x8(xth, xtl, xth, xtl);
|
|
gen_bswap16x8(xth, xtl, xth, xtl);
|
|
}
|
|
}
|
|
- set_cpu_vsr(xT(ctx->opcode), xth, true);
|
|
|
|
- set_cpu_vsr(xT(ctx->opcode), xtl, false);
|
|
|
|
|
|
+ set_cpu_vsr(a->rt, xth, true);
|
|
|
|
+ set_cpu_vsr(a->rt, xtl, false);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_lxvb16x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_LXVB16X(DisasContext *ctx, arg_LXVB16X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xth;
|
|
|
|
- TCGv_i64 xtl;
|
|
|
|
|
|
+ TCGv_i128 data;
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+
|
|
|
|
+ data = tcg_temp_new_i128();
|
|
|
|
+ gen_set_access_type(ctx, ACCESS_INT);
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
|
|
+ tcg_gen_qemu_ld_i128(data, EA, ctx->mem_idx,
|
|
|
|
+ MO_BE | MO_128 | MO_ATOM_IFALIGN_PAIR);
|
|
|
|
+ set_vsr_full(a->rt, data);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#if defined(TARGET_PPC64)
|
|
|
|
+static bool do_ld_st_vl(DisasContext *ctx, arg_X *a,
|
|
|
|
+ void (*helper)(TCGv_ptr, TCGv, TCGv_ptr, TCGv))
|
|
|
|
+{
|
|
|
|
+ TCGv EA;
|
|
|
|
+ TCGv_ptr xt;
|
|
|
|
+ if (a->rt < 32) {
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ } else {
|
|
|
|
+ REQUIRE_VECTOR(ctx);
|
|
}
|
|
}
|
|
- xth = tcg_temp_new_i64();
|
|
|
|
- xtl = tcg_temp_new_i64();
|
|
|
|
|
|
+ xt = gen_vsr_ptr(a->rt);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
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_BEUQ);
|
|
|
|
- tcg_gen_addi_tl(EA, EA, 8);
|
|
|
|
- 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);
|
|
|
|
|
|
+ EA = do_ea_calc_ra(ctx, a->ra);
|
|
|
|
+ helper(tcg_env, EA, xt, cpu_gpr[a->rb]);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
+#endif
|
|
|
|
|
|
-#ifdef TARGET_PPC64
|
|
|
|
-#define VSX_VECTOR_LOAD_STORE_LENGTH(name) \
|
|
|
|
-static void gen_##name(DisasContext *ctx) \
|
|
|
|
-{ \
|
|
|
|
- TCGv EA; \
|
|
|
|
- TCGv_ptr xt; \
|
|
|
|
- \
|
|
|
|
- if (xT(ctx->opcode) < 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; \
|
|
|
|
- } \
|
|
|
|
- } \
|
|
|
|
- EA = tcg_temp_new(); \
|
|
|
|
- xt = gen_vsr_ptr(xT(ctx->opcode)); \
|
|
|
|
- gen_set_access_type(ctx, ACCESS_INT); \
|
|
|
|
- gen_addr_register(ctx, EA); \
|
|
|
|
- gen_helper_##name(tcg_env, EA, xt, cpu_gpr[rB(ctx->opcode)]); \
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-VSX_VECTOR_LOAD_STORE_LENGTH(lxvl)
|
|
|
|
-VSX_VECTOR_LOAD_STORE_LENGTH(lxvll)
|
|
|
|
-VSX_VECTOR_LOAD_STORE_LENGTH(stxvl)
|
|
|
|
-VSX_VECTOR_LOAD_STORE_LENGTH(stxvll)
|
|
|
|
|
|
+static bool trans_LXVL(DisasContext *ctx, arg_LXVL *a)
|
|
|
|
+{
|
|
|
|
+ REQUIRE_64BIT(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+#if defined(TARGET_PPC64)
|
|
|
|
+ return do_ld_st_vl(ctx, a, gen_helper_LXVL);
|
|
|
|
+#else
|
|
|
|
+ qemu_build_not_reached();
|
|
#endif
|
|
#endif
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
|
|
-#define VSX_STORE_SCALAR(name, operation) \
|
|
|
|
-static void gen_##name(DisasContext *ctx) \
|
|
|
|
-{ \
|
|
|
|
- TCGv EA; \
|
|
|
|
- TCGv_i64 t0; \
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) { \
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
|
|
|
|
- return; \
|
|
|
|
- } \
|
|
|
|
- t0 = tcg_temp_new_i64(); \
|
|
|
|
- gen_set_access_type(ctx, ACCESS_INT); \
|
|
|
|
- EA = tcg_temp_new(); \
|
|
|
|
- gen_addr_reg_index(ctx, EA); \
|
|
|
|
- get_cpu_vsr(t0, xS(ctx->opcode), true); \
|
|
|
|
- gen_qemu_##operation(ctx, t0, EA); \
|
|
|
|
|
|
+static bool trans_LXVLL(DisasContext *ctx, arg_LXVLL *a)
|
|
|
|
+{
|
|
|
|
+ REQUIRE_64BIT(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+#if defined(TARGET_PPC64)
|
|
|
|
+ return do_ld_st_vl(ctx, a, gen_helper_LXVLL);
|
|
|
|
+#else
|
|
|
|
+ qemu_build_not_reached();
|
|
|
|
+#endif
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-VSX_STORE_SCALAR(stxsdx, st64_i64)
|
|
|
|
|
|
+static bool trans_STXVL(DisasContext *ctx, arg_STXVL *a)
|
|
|
|
+{
|
|
|
|
+ REQUIRE_64BIT(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+#if defined(TARGET_PPC64)
|
|
|
|
+ return do_ld_st_vl(ctx, a, gen_helper_STXVL);
|
|
|
|
+#else
|
|
|
|
+ qemu_build_not_reached();
|
|
|
|
+#endif
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
|
|
-VSX_STORE_SCALAR(stxsibx, st8_i64)
|
|
|
|
-VSX_STORE_SCALAR(stxsihx, st16_i64)
|
|
|
|
-VSX_STORE_SCALAR(stxsiwx, st32_i64)
|
|
|
|
-VSX_STORE_SCALAR(stxsspx, st32fs)
|
|
|
|
|
|
+static bool trans_STXVLL(DisasContext *ctx, arg_STXVLL *a)
|
|
|
|
+{
|
|
|
|
+ REQUIRE_64BIT(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+#if defined(TARGET_PPC64)
|
|
|
|
+ return do_ld_st_vl(ctx, a, gen_helper_STXVLL);
|
|
|
|
+#else
|
|
|
|
+ qemu_build_not_reached();
|
|
|
|
+#endif
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
|
|
-static void gen_stxvd2x(DisasContext *ctx)
|
|
|
|
|
|
+static bool do_stxs(DisasContext *ctx, arg_X *a,
|
|
|
|
+ void (*op)(DisasContext *, TCGv_i64, TCGv))
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
TCGv_i64 t0;
|
|
TCGv_i64 t0;
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
t0 = tcg_temp_new_i64();
|
|
t0 = tcg_temp_new_i64();
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
- get_cpu_vsr(t0, xS(ctx->opcode), true);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
|
|
+ get_cpu_vsr(t0, a->rt, true);
|
|
|
|
+ op(ctx, t0, EA);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX, STXSDX, do_stxs, gen_qemu_st64_i64);
|
|
|
|
+TRANS_FLAGS2(ISA300, STXSIBX, do_stxs, gen_qemu_st8_i64);
|
|
|
|
+TRANS_FLAGS2(ISA300, STXSIHX, do_stxs, gen_qemu_st16_i64);
|
|
|
|
+TRANS_FLAGS2(VSX207, STXSIWX, do_stxs, gen_qemu_st32_i64);
|
|
|
|
+TRANS_FLAGS2(VSX207, STXSSPX, do_stxs, gen_qemu_st32fs);
|
|
|
|
+
|
|
|
|
+static bool trans_STXVD2X(DisasContext *ctx, arg_STXVD2X *a)
|
|
|
|
+{
|
|
|
|
+ TCGv EA;
|
|
|
|
+ TCGv_i64 t0;
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
|
|
|
|
+
|
|
|
|
+ t0 = tcg_temp_new_i64();
|
|
|
|
+ gen_set_access_type(ctx, ACCESS_INT);
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
|
|
+ get_cpu_vsr(t0, a->rt, true);
|
|
gen_qemu_st64_i64(ctx, t0, EA);
|
|
gen_qemu_st64_i64(ctx, t0, EA);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
- get_cpu_vsr(t0, xS(ctx->opcode), false);
|
|
|
|
|
|
+ get_cpu_vsr(t0, a->rt, false);
|
|
gen_qemu_st64_i64(ctx, t0, EA);
|
|
gen_qemu_st64_i64(ctx, t0, EA);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_stxvw4x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_STXVW4X(DisasContext *ctx, arg_STXVW4X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xsh;
|
|
|
|
- TCGv_i64 xsl;
|
|
|
|
|
|
+ TCGv_i64 xsh, xsl;
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, VSX);
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
xsh = tcg_temp_new_i64();
|
|
xsh = tcg_temp_new_i64();
|
|
xsl = tcg_temp_new_i64();
|
|
xsl = tcg_temp_new_i64();
|
|
- get_cpu_vsr(xsh, xS(ctx->opcode), true);
|
|
|
|
- get_cpu_vsr(xsl, xS(ctx->opcode), false);
|
|
|
|
|
|
+ get_cpu_vsr(xsh, a->rt, true);
|
|
|
|
+ get_cpu_vsr(xsl, a->rt, false);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
if (ctx->le_mode) {
|
|
if (ctx->le_mode) {
|
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
TCGv_i64 t0 = tcg_temp_new_i64();
|
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
TCGv_i64 t1 = tcg_temp_new_i64();
|
|
@@ -342,25 +356,23 @@ static void gen_stxvw4x(DisasContext *ctx)
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
|
|
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
|
|
}
|
|
}
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_stxvh8x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_STXVH8X(DisasContext *ctx, arg_STXVH8X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xsh;
|
|
|
|
- TCGv_i64 xsl;
|
|
|
|
|
|
+ TCGv_i64 xsh, xsl;
|
|
|
|
+
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
xsh = tcg_temp_new_i64();
|
|
xsh = tcg_temp_new_i64();
|
|
xsl = tcg_temp_new_i64();
|
|
xsl = tcg_temp_new_i64();
|
|
- get_cpu_vsr(xsh, xS(ctx->opcode), true);
|
|
|
|
- get_cpu_vsr(xsl, xS(ctx->opcode), false);
|
|
|
|
|
|
+ get_cpu_vsr(xsh, a->rt, true);
|
|
|
|
+ get_cpu_vsr(xsl, a->rt, false);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
- EA = tcg_temp_new();
|
|
|
|
- gen_addr_reg_index(ctx, EA);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
if (ctx->le_mode) {
|
|
if (ctx->le_mode) {
|
|
TCGv_i64 outh = tcg_temp_new_i64();
|
|
TCGv_i64 outh = tcg_temp_new_i64();
|
|
TCGv_i64 outl = tcg_temp_new_i64();
|
|
TCGv_i64 outl = tcg_temp_new_i64();
|
|
@@ -374,28 +386,24 @@ static void gen_stxvh8x(DisasContext *ctx)
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_addi_tl(EA, EA, 8);
|
|
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
|
|
tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
|
|
}
|
|
}
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-static void gen_stxvb16x(DisasContext *ctx)
|
|
|
|
|
|
+static bool trans_STXVB16X(DisasContext *ctx, arg_STXVB16X *a)
|
|
{
|
|
{
|
|
TCGv EA;
|
|
TCGv EA;
|
|
- TCGv_i64 xsh;
|
|
|
|
- TCGv_i64 xsl;
|
|
|
|
|
|
+ TCGv_i128 data;
|
|
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) {
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU);
|
|
|
|
- return;
|
|
|
|
- }
|
|
|
|
- xsh = tcg_temp_new_i64();
|
|
|
|
- xsl = tcg_temp_new_i64();
|
|
|
|
- get_cpu_vsr(xsh, xS(ctx->opcode), true);
|
|
|
|
- get_cpu_vsr(xsl, xS(ctx->opcode), false);
|
|
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
+
|
|
|
|
+ data = tcg_temp_new_i128();
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
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_BEUQ);
|
|
|
|
- tcg_gen_addi_tl(EA, EA, 8);
|
|
|
|
- tcg_gen_qemu_st_i64(xsl, EA, ctx->mem_idx, MO_BEUQ);
|
|
|
|
|
|
+ EA = do_ea_calc(ctx, a->ra, cpu_gpr[a->rb]);
|
|
|
|
+ get_vsr_full(data, a->rt);
|
|
|
|
+ tcg_gen_qemu_st_i128(data, EA, ctx->mem_idx,
|
|
|
|
+ MO_BE | MO_128 | MO_ATOM_IFALIGN_PAIR);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
static void gen_mfvsrwz(DisasContext *ctx)
|
|
static void gen_mfvsrwz(DisasContext *ctx)
|
|
@@ -788,34 +796,28 @@ static bool do_xvcpsgn(DisasContext *ctx, arg_XX3 *a, unsigned vece)
|
|
TRANS(XVCPSGNSP, do_xvcpsgn, MO_32)
|
|
TRANS(XVCPSGNSP, do_xvcpsgn, MO_32)
|
|
TRANS(XVCPSGNDP, do_xvcpsgn, MO_64)
|
|
TRANS(XVCPSGNDP, do_xvcpsgn, MO_64)
|
|
|
|
|
|
-#define VSX_CMP(name, op1, op2, inval, type) \
|
|
|
|
-static void gen_##name(DisasContext *ctx) \
|
|
|
|
-{ \
|
|
|
|
- TCGv_i32 ignored; \
|
|
|
|
- TCGv_ptr xt, xa, xb; \
|
|
|
|
- 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)); \
|
|
|
|
- xb = gen_vsr_ptr(xB(ctx->opcode)); \
|
|
|
|
- if ((ctx->opcode >> (31 - 21)) & 1) { \
|
|
|
|
- gen_helper_##name(cpu_crf[6], tcg_env, xt, xa, xb); \
|
|
|
|
- } else { \
|
|
|
|
- ignored = tcg_temp_new_i32(); \
|
|
|
|
- gen_helper_##name(ignored, tcg_env, xt, xa, xb); \
|
|
|
|
- } \
|
|
|
|
|
|
+static bool do_cmp(DisasContext *ctx, arg_XX3_rc *a,
|
|
|
|
+ void (*helper)(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
|
|
|
|
+{
|
|
|
|
+ TCGv_i32 dest;
|
|
|
|
+ TCGv_ptr xt, xa, xb;
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ xt = gen_vsr_ptr(a->xt);
|
|
|
|
+ xa = gen_vsr_ptr(a->xa);
|
|
|
|
+ xb = gen_vsr_ptr(a->xb);
|
|
|
|
+ dest = a->rc ? cpu_crf[6] : tcg_temp_new_i32();
|
|
|
|
+ helper(dest, tcg_env, xt, xa, xb);
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
-VSX_CMP(xvcmpeqdp, 0x0C, 0x0C, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpgedp, 0x0C, 0x0E, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpgtdp, 0x0C, 0x0D, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpnedp, 0x0C, 0x0F, 0, PPC2_ISA300)
|
|
|
|
-VSX_CMP(xvcmpeqsp, 0x0C, 0x08, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpgesp, 0x0C, 0x0A, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpgtsp, 0x0C, 0x09, 0, PPC2_VSX)
|
|
|
|
-VSX_CMP(xvcmpnesp, 0x0C, 0x0B, 0, PPC2_VSX)
|
|
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPEQSP, do_cmp, gen_helper_XVCMPEQSP);
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPGTSP, do_cmp, gen_helper_XVCMPGTSP);
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPGESP, do_cmp, gen_helper_XVCMPGESP);
|
|
|
|
+TRANS_FLAGS2(ISA300, XVCMPNESP, do_cmp, gen_helper_XVCMPNESP);
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPEQDP, do_cmp, gen_helper_XVCMPEQDP);
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPGTDP, do_cmp, gen_helper_XVCMPGTDP);
|
|
|
|
+TRANS_FLAGS2(VSX, XVCMPGEDP, do_cmp, gen_helper_XVCMPGEDP);
|
|
|
|
+TRANS_FLAGS2(ISA300, XVCMPNEDP, do_cmp, gen_helper_XVCMPNEDP);
|
|
|
|
|
|
static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a)
|
|
static bool trans_XSCVQPDP(DisasContext *ctx, arg_X_tb_rc *a)
|
|
{
|
|
{
|
|
@@ -864,20 +866,6 @@ static void gen_##name(DisasContext *ctx) \
|
|
gen_helper_##name(tcg_env, opc); \
|
|
gen_helper_##name(tcg_env, opc); \
|
|
}
|
|
}
|
|
|
|
|
|
-#define GEN_VSX_HELPER_X3(name, op1, op2, inval, type) \
|
|
|
|
-static void gen_##name(DisasContext *ctx) \
|
|
|
|
-{ \
|
|
|
|
- TCGv_ptr xt, xa, xb; \
|
|
|
|
- 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)); \
|
|
|
|
- xb = gen_vsr_ptr(xB(ctx->opcode)); \
|
|
|
|
- gen_helper_##name(tcg_env, xt, xa, xb); \
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
#define GEN_VSX_HELPER_X2(name, op1, op2, inval, type) \
|
|
#define GEN_VSX_HELPER_X2(name, op1, op2, inval, type) \
|
|
static void gen_##name(DisasContext *ctx) \
|
|
static void gen_##name(DisasContext *ctx) \
|
|
{ \
|
|
{ \
|
|
@@ -983,12 +971,8 @@ static void gen_##name(DisasContext *ctx) \
|
|
set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
|
|
set_cpu_vsr(xT(ctx->opcode), tcg_constant_i64(0), false); \
|
|
}
|
|
}
|
|
|
|
|
|
-GEN_VSX_HELPER_X3(xsadddp, 0x00, 0x04, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R3(xsaddqp, 0x04, 0x00, 0, PPC2_ISA300)
|
|
-GEN_VSX_HELPER_X3(xssubdp, 0x00, 0x05, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xsmuldp, 0x00, 0x06, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R3(xsmulqp, 0x04, 0x01, 0, PPC2_ISA300)
|
|
-GEN_VSX_HELPER_X3(xsdivdp, 0x00, 0x07, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R3(xsdivqp, 0x04, 0x11, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xsredp, 0x14, 0x05, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xssqrtdp, 0x16, 0x04, 0, PPC2_VSX)
|
|
@@ -1001,8 +985,6 @@ GEN_VSX_HELPER_X2_AB(xscmpodp, 0x0C, 0x05, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xscmpudp, 0x0C, 0x04, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_R2_AB(xscmpoqp, 0x04, 0x04, 0, PPC2_VSX)
|
|
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_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_X2(xscvdphp, 0x16, 0x15, 0x11, 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_X2(xscvdpsp, 0x12, 0x10, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R2(xscvdpqp, 0x04, 0x1A, 0x16, PPC2_ISA300)
|
|
@@ -1233,27 +1215,17 @@ GEN_VSX_HELPER_R2(xsrqpi, 0x05, 0x00, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R2(xsrqpxp, 0x05, 0x01, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R2(xssqrtqp, 0x04, 0x19, 0x1B, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300)
|
|
GEN_VSX_HELPER_R3(xssubqp, 0x04, 0x10, 0, PPC2_ISA300)
|
|
-GEN_VSX_HELPER_X3(xsaddsp, 0x00, 0x00, 0, PPC2_VSX207)
|
|
|
|
-GEN_VSX_HELPER_X3(xssubsp, 0x00, 0x01, 0, PPC2_VSX207)
|
|
|
|
-GEN_VSX_HELPER_X3(xsmulsp, 0x00, 0x02, 0, PPC2_VSX207)
|
|
|
|
-GEN_VSX_HELPER_X3(xsdivsp, 0x00, 0x03, 0, PPC2_VSX207)
|
|
|
|
GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xsresp, 0x14, 0x01, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xssqrtsp, 0x16, 0x00, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xsrsqrtesp, 0x14, 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(xscvsxdsp, 0x10, 0x13, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
|
|
GEN_VSX_HELPER_X2(xscvuxdsp, 0x10, 0x12, 0, PPC2_VSX207)
|
|
|
|
|
|
-GEN_VSX_HELPER_X3(xvadddp, 0x00, 0x0C, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvsubdp, 0x00, 0x0D, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvmuldp, 0x00, 0x0E, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvdivdp, 0x00, 0x0F, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvredp, 0x14, 0x0D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvsqrtdp, 0x16, 0x0C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrsqrtedp, 0x14, 0x0C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xvtdivdp, 0x14, 0x0F, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X1(xvtsqrtdp, 0x14, 0x0E, 0, PPC2_VSX)
|
|
-GEN_VSX_HELPER_X3(xvmaxdp, 0x00, 0x1C, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvmindp, 0x00, 0x1D, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvdpsp, 0x12, 0x18, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvdpsxds, 0x10, 0x1D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvdpsxws, 0x10, 0x0D, 0, PPC2_VSX)
|
|
@@ -1269,17 +1241,11 @@ GEN_VSX_HELPER_X2(xvrdpim, 0x12, 0x0F, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrdpip, 0x12, 0x0E, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrdpiz, 0x12, 0x0D, 0, PPC2_VSX)
|
|
|
|
|
|
-GEN_VSX_HELPER_X3(xvaddsp, 0x00, 0x08, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvsubsp, 0x00, 0x09, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvmulsp, 0x00, 0x0A, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvdivsp, 0x00, 0x0B, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvresp, 0x14, 0x09, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvsqrtsp, 0x16, 0x08, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvrsqrtesp, 0x14, 0x08, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2_AB(xvtdivsp, 0x14, 0x0B, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X1(xvtsqrtsp, 0x14, 0x0A, 0, PPC2_VSX)
|
|
-GEN_VSX_HELPER_X3(xvmaxsp, 0x00, 0x18, 0, PPC2_VSX)
|
|
|
|
-GEN_VSX_HELPER_X3(xvminsp, 0x00, 0x19, 0, PPC2_VSX)
|
|
|
|
GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvspdp, 0x12, 0x1C, 0, PPC2_VSX)
|
|
GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300)
|
|
GEN_VSX_HELPER_X2(xvcvhpsp, 0x16, 0x1D, 0x18, PPC2_ISA300)
|
|
GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300)
|
|
GEN_VSX_HELPER_X2(xvcvsphp, 0x16, 0x1D, 0x19, PPC2_ISA300)
|
|
@@ -1609,26 +1575,24 @@ static void gen_xxbrw(DisasContext *ctx)
|
|
set_cpu_vsr(xT(ctx->opcode), xtl, false);
|
|
set_cpu_vsr(xT(ctx->opcode), xtl, false);
|
|
}
|
|
}
|
|
|
|
|
|
-#define VSX_LOGICAL(name, vece, tcg_op) \
|
|
|
|
-static void glue(gen_, name)(DisasContext *ctx) \
|
|
|
|
- { \
|
|
|
|
- if (unlikely(!ctx->vsx_enabled)) { \
|
|
|
|
- gen_exception(ctx, POWERPC_EXCP_VSXU); \
|
|
|
|
- return; \
|
|
|
|
- } \
|
|
|
|
- tcg_op(vece, vsr_full_offset(xT(ctx->opcode)), \
|
|
|
|
- vsr_full_offset(xA(ctx->opcode)), \
|
|
|
|
- vsr_full_offset(xB(ctx->opcode)), 16, 16); \
|
|
|
|
- }
|
|
|
|
|
|
+static bool do_logical_op(DisasContext *ctx, arg_XX3 *a, unsigned vece,
|
|
|
|
+ void (*helper)(unsigned, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t))
|
|
|
|
+{
|
|
|
|
+ REQUIRE_VSX(ctx);
|
|
|
|
+ helper(vece, vsr_full_offset(a->xt),
|
|
|
|
+ vsr_full_offset(a->xa),
|
|
|
|
+ vsr_full_offset(a->xb), 16, 16);
|
|
|
|
+ return true;
|
|
|
|
+}
|
|
|
|
|
|
-VSX_LOGICAL(xxland, MO_64, tcg_gen_gvec_and)
|
|
|
|
-VSX_LOGICAL(xxlandc, MO_64, tcg_gen_gvec_andc)
|
|
|
|
-VSX_LOGICAL(xxlor, MO_64, tcg_gen_gvec_or)
|
|
|
|
-VSX_LOGICAL(xxlxor, MO_64, tcg_gen_gvec_xor)
|
|
|
|
-VSX_LOGICAL(xxlnor, MO_64, tcg_gen_gvec_nor)
|
|
|
|
-VSX_LOGICAL(xxleqv, MO_64, tcg_gen_gvec_eqv)
|
|
|
|
-VSX_LOGICAL(xxlnand, MO_64, tcg_gen_gvec_nand)
|
|
|
|
-VSX_LOGICAL(xxlorc, MO_64, tcg_gen_gvec_orc)
|
|
|
|
|
|
+TRANS_FLAGS2(VSX, XXLAND, do_logical_op, MO_64, tcg_gen_gvec_and);
|
|
|
|
+TRANS_FLAGS2(VSX, XXLANDC, do_logical_op, MO_64, tcg_gen_gvec_andc);
|
|
|
|
+TRANS_FLAGS2(VSX, XXLOR, do_logical_op, MO_64, tcg_gen_gvec_or);
|
|
|
|
+TRANS_FLAGS2(VSX, XXLXOR, do_logical_op, MO_64, tcg_gen_gvec_xor);
|
|
|
|
+TRANS_FLAGS2(VSX, XXLNOR, do_logical_op, MO_64, tcg_gen_gvec_nor);
|
|
|
|
+TRANS_FLAGS2(VSX207, XXLEQV, do_logical_op, MO_64, tcg_gen_gvec_eqv);
|
|
|
|
+TRANS_FLAGS2(VSX207, XXLNAND, do_logical_op, MO_64, tcg_gen_gvec_nand);
|
|
|
|
+TRANS_FLAGS2(VSX207, XXLORC, do_logical_op, MO_64, tcg_gen_gvec_orc);
|
|
|
|
|
|
#define VSX_XXMRG(name, high) \
|
|
#define VSX_XXMRG(name, high) \
|
|
static void glue(gen_, name)(DisasContext *ctx) \
|
|
static void glue(gen_, name)(DisasContext *ctx) \
|
|
@@ -2215,13 +2179,13 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
|
|
int rt, bool store, bool paired)
|
|
int rt, bool store, bool paired)
|
|
{
|
|
{
|
|
TCGv ea;
|
|
TCGv ea;
|
|
- TCGv_i64 xt;
|
|
|
|
|
|
+ TCGv_i128 data;
|
|
MemOp mop;
|
|
MemOp mop;
|
|
int rt1, rt2;
|
|
int rt1, rt2;
|
|
|
|
|
|
- xt = tcg_temp_new_i64();
|
|
|
|
|
|
+ data = tcg_temp_new_i128();
|
|
|
|
|
|
- mop = DEF_MEMOP(MO_UQ);
|
|
|
|
|
|
+ mop = DEF_MEMOP(MO_128 | MO_ATOM_IFALIGN_PAIR);
|
|
|
|
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
gen_set_access_type(ctx, ACCESS_INT);
|
|
ea = do_ea_calc(ctx, ra, displ);
|
|
ea = do_ea_calc(ctx, ra, displ);
|
|
@@ -2235,32 +2199,20 @@ static bool do_lstxv(DisasContext *ctx, int ra, TCGv displ,
|
|
}
|
|
}
|
|
|
|
|
|
if (store) {
|
|
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);
|
|
|
|
|
|
+ get_vsr_full(data, rt1);
|
|
|
|
+ tcg_gen_qemu_st_i128(data, ea, ctx->mem_idx, mop);
|
|
if (paired) {
|
|
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);
|
|
|
|
|
|
+ gen_addr_add(ctx, ea, ea, 16);
|
|
|
|
+ get_vsr_full(data, rt2);
|
|
|
|
+ tcg_gen_qemu_st_i128(data, ea, ctx->mem_idx, mop);
|
|
}
|
|
}
|
|
} else {
|
|
} 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);
|
|
|
|
|
|
+ tcg_gen_qemu_ld_i128(data, ea, ctx->mem_idx, mop);
|
|
|
|
+ set_vsr_full(rt1, data);
|
|
if (paired) {
|
|
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);
|
|
|
|
|
|
+ gen_addr_add(ctx, ea, ea, 16);
|
|
|
|
+ tcg_gen_qemu_ld_i128(data, ea, ctx->mem_idx, mop);
|
|
|
|
+ set_vsr_full(rt2, data);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
return true;
|
|
@@ -2712,8 +2664,6 @@ static bool do_helper_XX3(DisasContext *ctx, arg_XX3 *a,
|
|
void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
|
|
void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
|
|
{
|
|
{
|
|
TCGv_ptr xt, xa, xb;
|
|
TCGv_ptr xt, xa, xb;
|
|
-
|
|
|
|
- REQUIRE_INSNS_FLAGS2(ctx, ISA300);
|
|
|
|
REQUIRE_VSX(ctx);
|
|
REQUIRE_VSX(ctx);
|
|
|
|
|
|
xt = gen_vsr_ptr(a->xt);
|
|
xt = gen_vsr_ptr(a->xt);
|
|
@@ -2724,13 +2674,40 @@ static bool do_helper_XX3(DisasContext *ctx, arg_XX3 *a,
|
|
return true;
|
|
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)
|
|
|
|
|
|
+TRANS_FLAGS2(ISA300, XSCMPEQDP, do_helper_XX3, gen_helper_XSCMPEQDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSCMPGEDP, do_helper_XX3, gen_helper_XSCMPGEDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSCMPGTDP, do_helper_XX3, gen_helper_XSCMPGTDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSMAXCDP, do_helper_XX3, gen_helper_XSMAXCDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSMINCDP, do_helper_XX3, gen_helper_XSMINCDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSMAXJDP, do_helper_XX3, gen_helper_XSMAXJDP)
|
|
|
|
+TRANS_FLAGS2(ISA300, XSMINJDP, do_helper_XX3, gen_helper_XSMINJDP)
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX207, XSADDSP, do_helper_XX3, gen_helper_XSADDSP)
|
|
|
|
+TRANS_FLAGS2(VSX207, XSSUBSP, do_helper_XX3, gen_helper_XSSUBSP)
|
|
|
|
+TRANS_FLAGS2(VSX207, XSMULSP, do_helper_XX3, gen_helper_XSMULSP)
|
|
|
|
+TRANS_FLAGS2(VSX207, XSDIVSP, do_helper_XX3, gen_helper_XSDIVSP)
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX, XSADDDP, do_helper_XX3, gen_helper_XSADDDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XSSUBDP, do_helper_XX3, gen_helper_XSSUBDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XSMULDP, do_helper_XX3, gen_helper_XSMULDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XSDIVDP, do_helper_XX3, gen_helper_XSDIVDP)
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX, XVADDSP, do_helper_XX3, gen_helper_XVADDSP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVSUBSP, do_helper_XX3, gen_helper_XVSUBSP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMULSP, do_helper_XX3, gen_helper_XVMULSP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVDIVSP, do_helper_XX3, gen_helper_XVDIVSP)
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX, XVADDDP, do_helper_XX3, gen_helper_XVADDDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVSUBDP, do_helper_XX3, gen_helper_XVSUBDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMULDP, do_helper_XX3, gen_helper_XVMULDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVDIVDP, do_helper_XX3, gen_helper_XVDIVDP)
|
|
|
|
+
|
|
|
|
+TRANS_FLAGS2(VSX, XSMAXDP, do_helper_XX3, gen_helper_XSMAXDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XSMINDP, do_helper_XX3, gen_helper_XSMINDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMAXSP, do_helper_XX3, gen_helper_XVMAXSP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMINSP, do_helper_XX3, gen_helper_XVMINSP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMAXDP, do_helper_XX3, gen_helper_XVMAXDP)
|
|
|
|
+TRANS_FLAGS2(VSX, XVMINDP, do_helper_XX3, gen_helper_XVMINDP)
|
|
|
|
|
|
static bool do_helper_X(arg_X *a,
|
|
static bool do_helper_X(arg_X *a,
|
|
void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
|
|
void (*helper)(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr))
|
|
@@ -2910,4 +2887,3 @@ TRANS64(PMXVF64GERNN, do_ger, gen_helper_XVF64GERNN)
|
|
#undef GEN_XX2IFORM
|
|
#undef GEN_XX2IFORM
|
|
#undef GEN_XX3_RC_FORM
|
|
#undef GEN_XX3_RC_FORM
|
|
#undef GEN_XX3FORM_DM
|
|
#undef GEN_XX3FORM_DM
|
|
-#undef VSX_LOGICAL
|
|
|