target/arm: Implement MVE VQSHL (vector)
Implement the MVE VQSHL insn (encoding T4, which is the vector-shift-by-vector version). The DO_SQSHL_OP and DO_UQSHL_OP macros here are derived from the neon_helper.c code for qshl_u{8,16,32} and qshl_s{8,16,32}. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210617121628.20116-33-peter.maydell@linaro.org
This commit is contained in:
parent
f741707bb3
commit
483da66139
@ -169,6 +169,14 @@ DEF_HELPER_FLAGS_4(mve_vqsubub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqsubuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqsubuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
||||
DEF_HELPER_FLAGS_4(mve_vqshlsb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqshlsh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqshlsw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
||||
DEF_HELPER_FLAGS_4(mve_vqshlub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqshluh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqshluw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
||||
DEF_HELPER_FLAGS_4(mve_vadd_scalarb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(mve_vadd_scalarh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
|
||||
DEF_HELPER_FLAGS_4(mve_vadd_scalarw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32)
|
||||
|
@ -40,6 +40,15 @@
|
||||
@2op .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn
|
||||
@2op_nosz .... .... .... .... .... .... .... .... &2op qd=%qd qm=%qm qn=%qn size=0
|
||||
|
||||
# The _rev suffix indicates that Vn and Vm are reversed. This is
|
||||
# the case for shifts. In the Arm ARM these insns are documented
|
||||
# with the Vm and Vn fields in their usual places, but in the
|
||||
# assembly the operands are listed "backwards", ie in the order
|
||||
# Qd, Qm, Qn where other insns use Qd, Qn, Qm. For QEMU we choose
|
||||
# to consider Vm and Vn as being in different fields in the insn.
|
||||
# This gives us consistency with A64 and Neon.
|
||||
@2op_rev .... .... .. size:2 .... .... .... .... .... &2op qd=%qd qm=%qn qn=%qm
|
||||
|
||||
@2scalar .... .... .. size:2 .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
|
||||
@2scalar_nosz .... .... .... .... .... .... .... rm:4 &2scalar qd=%qd qn=%qn
|
||||
|
||||
@ -121,6 +130,9 @@ VQADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 1 ... 0 @2op
|
||||
VQSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
|
||||
VQSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 1 ... 0 @2op
|
||||
|
||||
VQSHL_S 111 0 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
|
||||
VQSHL_U 111 1 1111 0 . .. ... 0 ... 0 0100 . 1 . 1 ... 0 @2op_rev
|
||||
|
||||
# Vector miscellaneous
|
||||
|
||||
VCLS 1111 1111 1 . 11 .. 00 ... 0 0100 01 . 0 ... 0 @1op
|
||||
|
@ -389,6 +389,18 @@ DO_1OP(vfnegs, 8, uint64_t, DO_FNEGS)
|
||||
mve_advance_vpt(env); \
|
||||
}
|
||||
|
||||
/* provide unsigned 2-op helpers for all sizes */
|
||||
#define DO_2OP_SAT_U(OP, FN) \
|
||||
DO_2OP_SAT(OP##b, 1, uint8_t, FN) \
|
||||
DO_2OP_SAT(OP##h, 2, uint16_t, FN) \
|
||||
DO_2OP_SAT(OP##w, 4, uint32_t, FN)
|
||||
|
||||
/* provide signed 2-op helpers for all sizes */
|
||||
#define DO_2OP_SAT_S(OP, FN) \
|
||||
DO_2OP_SAT(OP##b, 1, int8_t, FN) \
|
||||
DO_2OP_SAT(OP##h, 2, int16_t, FN) \
|
||||
DO_2OP_SAT(OP##w, 4, int32_t, FN)
|
||||
|
||||
#define DO_AND(N, M) ((N) & (M))
|
||||
#define DO_BIC(N, M) ((N) & ~(M))
|
||||
#define DO_ORR(N, M) ((N) | (M))
|
||||
@ -577,6 +589,28 @@ DO_2OP_SAT(vqsubsb, 1, int8_t, DO_SQSUB_B)
|
||||
DO_2OP_SAT(vqsubsh, 2, int16_t, DO_SQSUB_H)
|
||||
DO_2OP_SAT(vqsubsw, 4, int32_t, DO_SQSUB_W)
|
||||
|
||||
/*
|
||||
* This wrapper fixes up the impedance mismatch between do_sqrshl_bhs()
|
||||
* and friends wanting a uint32_t* sat and our needing a bool*.
|
||||
*/
|
||||
#define WRAP_QRSHL_HELPER(FN, N, M, ROUND, satp) \
|
||||
({ \
|
||||
uint32_t su32 = 0; \
|
||||
typeof(N) r = FN(N, (int8_t)(M), sizeof(N) * 8, ROUND, &su32); \
|
||||
if (su32) { \
|
||||
*satp = true; \
|
||||
} \
|
||||
r; \
|
||||
})
|
||||
|
||||
#define DO_SQSHL_OP(N, M, satp) \
|
||||
WRAP_QRSHL_HELPER(do_sqrshl_bhs, N, M, false, satp)
|
||||
#define DO_UQSHL_OP(N, M, satp) \
|
||||
WRAP_QRSHL_HELPER(do_uqrshl_bhs, N, M, false, satp)
|
||||
|
||||
DO_2OP_SAT_S(vqshls, DO_SQSHL_OP)
|
||||
DO_2OP_SAT_U(vqshlu, DO_UQSHL_OP)
|
||||
|
||||
#define DO_2OP_SCALAR(OP, ESIZE, TYPE, FN) \
|
||||
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, void *vn, \
|
||||
uint32_t rm) \
|
||||
|
@ -402,6 +402,8 @@ DO_2OP(VQADD_S, vqadds)
|
||||
DO_2OP(VQADD_U, vqaddu)
|
||||
DO_2OP(VQSUB_S, vqsubs)
|
||||
DO_2OP(VQSUB_U, vqsubu)
|
||||
DO_2OP(VQSHL_S, vqshls)
|
||||
DO_2OP(VQSHL_U, vqshlu)
|
||||
|
||||
static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
|
||||
MVEGenTwoOpScalarFn fn)
|
||||
|
Loading…
Reference in New Issue
Block a user