target/ppc: Implement Vector Insert from GPR using GPR index insns
Implements the following PowerISA v3.1 instructions: vinsblx: Vector Insert Byte from GPR using GPR-specified Left-Index vinshlx: Vector Insert Halfword from GPR using GPR-specified Left-Index vinswlx: Vector Insert Word from GPR using GPR-specified Left-Index vinsdlx: Vector Insert Doubleword from GPR using GPR-specified Left-Index vinsbrx: Vector Insert Byte from GPR using GPR-specified Right-Index vinshrx: Vector Insert Halfword from GPR using GPR-specified Right-Index vinswrx: Vector Insert Word from GPR using GPR-specified Right-Index vinsdrx: Vector Insert Doubleword from GPR using GPR-specified Right-Index The helpers and do_vinsx receive i64 to allow code sharing with the future implementation of Vector Insert from VSR using GPR Index. Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br> Message-Id: <20211104123719.323713-6-matheus.ferst@eldorado.org.br> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
2c716b4da5
commit
2cc12af399
@ -228,6 +228,10 @@ DEF_HELPER_3(vinsertb, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinserth, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinsertw, void, avr, avr, i32)
|
||||
DEF_HELPER_3(vinsertd, void, avr, avr, i32)
|
||||
DEF_HELPER_4(VINSBLX, void, env, avr, i64, tl)
|
||||
DEF_HELPER_4(VINSHLX, void, env, avr, i64, tl)
|
||||
DEF_HELPER_4(VINSWLX, void, env, avr, i64, tl)
|
||||
DEF_HELPER_4(VINSDLX, void, env, avr, i64, tl)
|
||||
DEF_HELPER_2(vextsb2w, void, avr, avr)
|
||||
DEF_HELPER_2(vextsh2w, void, avr, avr)
|
||||
DEF_HELPER_2(vextsb2d, void, avr, avr)
|
||||
|
@ -344,5 +344,14 @@ VPEXTD 000100 ..... ..... ..... 10110001101 @VX
|
||||
|
||||
## Vector Permute and Formatting Instruction
|
||||
|
||||
VINSBLX 000100 ..... ..... ..... 01000001111 @VX
|
||||
VINSBRX 000100 ..... ..... ..... 01100001111 @VX
|
||||
VINSHLX 000100 ..... ..... ..... 01001001111 @VX
|
||||
VINSHRX 000100 ..... ..... ..... 01101001111 @VX
|
||||
VINSWLX 000100 ..... ..... ..... 01010001111 @VX
|
||||
VINSWRX 000100 ..... ..... ..... 01110001111 @VX
|
||||
VINSDLX 000100 ..... ..... ..... 01011001111 @VX
|
||||
VINSDRX 000100 ..... ..... ..... 01111001111 @VX
|
||||
|
||||
VSLDBI 000100 ..... ..... ..... 00 ... 010110 @VN
|
||||
VSRDBI 000100 ..... ..... ..... 01 ... 010110 @VN
|
||||
|
@ -1632,6 +1632,36 @@ VINSERT(h, u16)
|
||||
VINSERT(w, u32)
|
||||
VINSERT(d, u64)
|
||||
#undef VINSERT
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#define ELEM_ADDR(VEC, IDX, SIZE) (&(VEC)->u8[IDX])
|
||||
#else
|
||||
#define ELEM_ADDR(VEC, IDX, SIZE) (&(VEC)->u8[15 - (IDX)] - (SIZE) + 1)
|
||||
#endif
|
||||
|
||||
#define VINSX(SUFFIX, TYPE) \
|
||||
void glue(glue(helper_VINS, SUFFIX), LX)(CPUPPCState *env, ppc_avr_t *t, \
|
||||
uint64_t val, target_ulong index) \
|
||||
{ \
|
||||
const int maxidx = ARRAY_SIZE(t->u8) - sizeof(TYPE); \
|
||||
target_long idx = index; \
|
||||
\
|
||||
if (idx < 0 || idx > maxidx) { \
|
||||
idx = idx < 0 ? sizeof(TYPE) - idx : idx; \
|
||||
qemu_log_mask(LOG_GUEST_ERROR, \
|
||||
"Invalid index for Vector Insert Element after 0x" TARGET_FMT_lx \
|
||||
", RA = " TARGET_FMT_ld " > %d\n", env->nip, idx, maxidx); \
|
||||
} else { \
|
||||
TYPE src = val; \
|
||||
memcpy(ELEM_ADDR(t, idx, sizeof(TYPE)), &src, sizeof(TYPE)); \
|
||||
} \
|
||||
}
|
||||
VINSX(B, uint8_t)
|
||||
VINSX(H, uint16_t)
|
||||
VINSX(W, uint32_t)
|
||||
VINSX(D, uint64_t)
|
||||
#undef ELEM_ADDR
|
||||
#undef VINSX
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#define VEXTRACT(suffix, element) \
|
||||
void helper_vextract##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t index) \
|
||||
|
@ -1238,6 +1238,56 @@ GEN_VXFORM_DUAL(vspltish, PPC_ALTIVEC, PPC_NONE,
|
||||
GEN_VXFORM_DUAL(vspltisw, PPC_ALTIVEC, PPC_NONE,
|
||||
vinsertw, PPC_NONE, PPC2_ISA300);
|
||||
|
||||
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(cpu_env, t, rb, idx);
|
||||
|
||||
tcg_temp_free_ptr(t);
|
||||
tcg_temp_free(idx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_vinsx_VX(DisasContext *ctx, arg_VX *a, int size, bool right,
|
||||
void (*gen_helper)(TCGv_ptr, TCGv_ptr, TCGv_i64, TCGv))
|
||||
{
|
||||
bool ok;
|
||||
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]);
|
||||
|
||||
ok = do_vinsx(ctx, a->vrt, size, right, cpu_gpr[a->vra], val, gen_helper);
|
||||
|
||||
tcg_temp_free_i64(val);
|
||||
return ok;
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
static void gen_vsldoi(DisasContext *ctx)
|
||||
{
|
||||
TCGv_ptr ra, rb, rd;
|
||||
|
Loading…
Reference in New Issue
Block a user