target/arm: Implement MVE integer vector-vs-scalar comparisons

Implement the MVE integer vector comparison instructions that compare
each element against a scalar from a general purpose register.  These
are "VCMP (vector)" encodings T4, T5 and T6 and "VPT (vector)"
encodings T4, T5 and T6.

We have to move the decodetree pattern for VPST, because it
overlaps with VCMP T4 with size = 0b11.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Peter Maydell 2021-08-13 17:11:51 +01:00
parent eff5d9a9bd
commit cce81873bc
4 changed files with 126 additions and 11 deletions

View file

@ -1787,15 +1787,43 @@ DO_VIWDUP_ALL(vdwdup, do_sub_wrap)
mve_advance_vpt(env); \
}
#define DO_VCMP_S(OP, FN) \
DO_VCMP(OP##b, 1, int8_t, FN) \
DO_VCMP(OP##h, 2, int16_t, FN) \
DO_VCMP(OP##w, 4, int32_t, FN)
#define DO_VCMP_SCALAR(OP, ESIZE, TYPE, FN) \
void HELPER(glue(mve_, OP))(CPUARMState *env, void *vn, \
uint32_t rm) \
{ \
TYPE *n = vn; \
uint16_t mask = mve_element_mask(env); \
uint16_t eci_mask = mve_eci_mask(env); \
uint16_t beatpred = 0; \
uint16_t emask = MAKE_64BIT_MASK(0, ESIZE); \
unsigned e; \
for (e = 0; e < 16 / ESIZE; e++) { \
bool r = FN(n[H##ESIZE(e)], (TYPE)rm); \
/* Comparison sets 0/1 bits for each byte in the element */ \
beatpred |= r * emask; \
emask <<= ESIZE; \
} \
beatpred &= mask; \
env->v7m.vpr = (env->v7m.vpr & ~(uint32_t)eci_mask) | \
(beatpred & eci_mask); \
mve_advance_vpt(env); \
}
#define DO_VCMP_U(OP, FN) \
DO_VCMP(OP##b, 1, uint8_t, FN) \
DO_VCMP(OP##h, 2, uint16_t, FN) \
DO_VCMP(OP##w, 4, uint32_t, FN)
#define DO_VCMP_S(OP, FN) \
DO_VCMP(OP##b, 1, int8_t, FN) \
DO_VCMP(OP##h, 2, int16_t, FN) \
DO_VCMP(OP##w, 4, int32_t, FN) \
DO_VCMP_SCALAR(OP##_scalarb, 1, int8_t, FN) \
DO_VCMP_SCALAR(OP##_scalarh, 2, int16_t, FN) \
DO_VCMP_SCALAR(OP##_scalarw, 4, int32_t, FN)
#define DO_VCMP_U(OP, FN) \
DO_VCMP(OP##b, 1, uint8_t, FN) \
DO_VCMP(OP##h, 2, uint16_t, FN) \
DO_VCMP(OP##w, 4, uint32_t, FN) \
DO_VCMP_SCALAR(OP##_scalarb, 1, uint8_t, FN) \
DO_VCMP_SCALAR(OP##_scalarh, 2, uint16_t, FN) \
DO_VCMP_SCALAR(OP##_scalarw, 4, uint32_t, FN)
#define DO_EQ(N, M) ((N) == (M))
#define DO_NE(N, M) ((N) != (M))