mirror of https://github.com/xemu-project/xemu.git
target/arm: Implement MVE VDUP
Implement the MVE VDUP insn, which duplicates a value from a general-purpose register into every lane of a vector register (subject to predication). Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210617121628.20116-11-peter.maydell@linaro.org
This commit is contained in:
parent
614dd4f3ba
commit
ab59362fca
|
@ -33,6 +33,8 @@ DEF_HELPER_FLAGS_3(mve_vstrb_h, TCG_CALL_NO_WG, void, env, ptr, i32)
|
||||||
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
|
DEF_HELPER_FLAGS_3(mve_vstrb_w, TCG_CALL_NO_WG, void, env, ptr, i32)
|
||||||
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
|
DEF_HELPER_FLAGS_3(mve_vstrh_w, TCG_CALL_NO_WG, void, env, ptr, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_FLAGS_3(mve_vdup, TCG_CALL_NO_WG, void, env, ptr, i32)
|
||||||
|
|
||||||
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
DEF_HELPER_FLAGS_3(mve_vclsb, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
||||||
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
DEF_HELPER_FLAGS_3(mve_vclsh, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
||||||
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
DEF_HELPER_FLAGS_3(mve_vclsw, TCG_CALL_NO_WG, void, env, ptr, ptr)
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
|
|
||||||
%qd 22:1 13:3
|
%qd 22:1 13:3
|
||||||
%qm 5:1 1:3
|
%qm 5:1 1:3
|
||||||
|
%qn 7:1 17:3
|
||||||
|
|
||||||
&vldr_vstr rn qd imm p a w size l u
|
&vldr_vstr rn qd imm p a w size l u
|
||||||
&1op qd qm size
|
&1op qd qm size
|
||||||
|
@ -82,3 +83,12 @@ VABS 1111 1111 1 . 11 .. 01 ... 0 0011 01 . 0 ... 0 @1op
|
||||||
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
|
VABS_fp 1111 1111 1 . 11 .. 01 ... 0 0111 01 . 0 ... 0 @1op
|
||||||
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
|
VNEG 1111 1111 1 . 11 .. 01 ... 0 0011 11 . 0 ... 0 @1op
|
||||||
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
|
VNEG_fp 1111 1111 1 . 11 .. 01 ... 0 0111 11 . 0 ... 0 @1op
|
||||||
|
|
||||||
|
&vdup qd rt size
|
||||||
|
# Qd is in the fields usually named Qn
|
||||||
|
@vdup .... .... . . .. ... . rt:4 .... . . . . .... qd=%qn &vdup
|
||||||
|
|
||||||
|
# B and E bits encode size, which we decode here to the usual size values
|
||||||
|
VDUP 1110 1110 1 1 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=0
|
||||||
|
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 1 1 0000 @vdup size=1
|
||||||
|
VDUP 1110 1110 1 0 10 ... 0 .... 1011 . 0 0 1 0000 @vdup size=2
|
||||||
|
|
|
@ -246,6 +246,22 @@ static void mergemask_sq(int64_t *d, int64_t r, uint16_t mask)
|
||||||
uint64_t *: mergemask_uq, \
|
uint64_t *: mergemask_uq, \
|
||||||
int64_t *: mergemask_sq)(D, R, M)
|
int64_t *: mergemask_sq)(D, R, M)
|
||||||
|
|
||||||
|
void HELPER(mve_vdup)(CPUARMState *env, void *vd, uint32_t val)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The generated code already replicated an 8 or 16 bit constant
|
||||||
|
* into the 32-bit value, so we only need to write the 32-bit
|
||||||
|
* value to all elements of the Qreg, allowing for predication.
|
||||||
|
*/
|
||||||
|
uint32_t *d = vd;
|
||||||
|
uint16_t mask = mve_element_mask(env);
|
||||||
|
unsigned e;
|
||||||
|
for (e = 0; e < 16 / 4; e++, mask >>= 4) {
|
||||||
|
mergemask(&d[H4(e)], val, mask);
|
||||||
|
}
|
||||||
|
mve_advance_vpt(env);
|
||||||
|
}
|
||||||
|
|
||||||
#define DO_1OP(OP, ESIZE, TYPE, FN) \
|
#define DO_1OP(OP, ESIZE, TYPE, FN) \
|
||||||
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
|
void HELPER(mve_##OP)(CPUARMState *env, void *vd, void *vm) \
|
||||||
{ \
|
{ \
|
||||||
|
|
|
@ -162,6 +162,33 @@ DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h)
|
||||||
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
|
DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w)
|
||||||
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
|
DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w)
|
||||||
|
|
||||||
|
static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
|
||||||
|
{
|
||||||
|
TCGv_ptr qd;
|
||||||
|
TCGv_i32 rt;
|
||||||
|
|
||||||
|
if (!dc_isar_feature(aa32_mve, s) ||
|
||||||
|
!mve_check_qreg_bank(s, a->qd)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (a->rt == 13 || a->rt == 15) {
|
||||||
|
/* UNPREDICTABLE; we choose to UNDEF */
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!mve_eci_check(s) || !vfp_access_check(s)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
qd = mve_qreg_ptr(a->qd);
|
||||||
|
rt = load_reg(s, a->rt);
|
||||||
|
tcg_gen_dup_i32(a->size, rt, rt);
|
||||||
|
gen_helper_mve_vdup(cpu_env, qd, rt);
|
||||||
|
tcg_temp_free_ptr(qd);
|
||||||
|
tcg_temp_free_i32(rt);
|
||||||
|
mve_update_eci(s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
|
static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
|
||||||
{
|
{
|
||||||
TCGv_ptr qd, qm;
|
TCGv_ptr qd, qm;
|
||||||
|
|
Loading…
Reference in New Issue