target/arm: Implement MVE VMULL (polynomial)
Implement the MVE VMULL (polynomial) insn. Unlike Neon, this comes in two flavours: 8x8->16 and a 16x16->32. Also unlike Neon, the inputs are in either the low or the high half of each double-width element. The assembler for this insn indicates the size with "P8" or "P16", encoded into bit 28 as size = 0 or 1. We choose to follow the same encoding as VQDMULL and decode this into a->size as MO_16 or MO_32 indicating the size of the result elements. This then carries through to the helper function names where it then matches up with the existing pmull_h() which does an 8x8->16 operation and a new pmull_w() which does the 16x16->32. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
41704cc262
commit
c1bd78cb06
@ -145,6 +145,11 @@ DEF_HELPER_FLAGS_4(mve_vmulltub, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vmulltuh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vmulltuw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
||||
DEF_HELPER_FLAGS_4(mve_vmullpbh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vmullpth, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vmullpbw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vmullptw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
||||
DEF_HELPER_FLAGS_4(mve_vqdmulhb, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqdmulhh, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
DEF_HELPER_FLAGS_4(mve_vqdmulhw, TCG_CALL_NO_WG, void, env, ptr, ptr, ptr)
|
||||
|
@ -173,10 +173,16 @@ VHADD_U 111 1 1111 0 . .. ... 0 ... 0 0000 . 1 . 0 ... 0 @2op
|
||||
VHSUB_S 111 0 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
|
||||
VHSUB_U 111 1 1111 0 . .. ... 0 ... 0 0010 . 1 . 0 ... 0 @2op
|
||||
|
||||
VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
|
||||
VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
|
||||
VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
|
||||
VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
|
||||
{
|
||||
VMULLP_B 111 . 1110 0 . 11 ... 1 ... 0 1110 . 0 . 0 ... 0 @2op_sz28
|
||||
VMULL_BS 111 0 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
|
||||
VMULL_BU 111 1 1110 0 . .. ... 1 ... 0 1110 . 0 . 0 ... 0 @2op
|
||||
}
|
||||
{
|
||||
VMULLP_T 111 . 1110 0 . 11 ... 1 ... 1 1110 . 0 . 0 ... 0 @2op_sz28
|
||||
VMULL_TS 111 0 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
|
||||
VMULL_TU 111 1 1110 0 . .. ... 1 ... 1 1110 . 0 . 0 ... 0 @2op
|
||||
}
|
||||
|
||||
VQDMULH 1110 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
|
||||
VQRDMULH 1111 1111 0 . .. ... 0 ... 0 1011 . 1 . 0 ... 0 @2op
|
||||
|
@ -481,6 +481,22 @@ DO_2OP_L(vmulltub, 1, 1, uint8_t, 2, uint16_t, DO_MUL)
|
||||
DO_2OP_L(vmulltuh, 1, 2, uint16_t, 4, uint32_t, DO_MUL)
|
||||
DO_2OP_L(vmulltuw, 1, 4, uint32_t, 8, uint64_t, DO_MUL)
|
||||
|
||||
/*
|
||||
* Polynomial multiply. We can always do this generating 64 bits
|
||||
* of the result at a time, so we don't need to use DO_2OP_L.
|
||||
*/
|
||||
#define VMULLPH_MASK 0x00ff00ff00ff00ffULL
|
||||
#define VMULLPW_MASK 0x0000ffff0000ffffULL
|
||||
#define DO_VMULLPBH(N, M) pmull_h((N) & VMULLPH_MASK, (M) & VMULLPH_MASK)
|
||||
#define DO_VMULLPTH(N, M) DO_VMULLPBH((N) >> 8, (M) >> 8)
|
||||
#define DO_VMULLPBW(N, M) pmull_w((N) & VMULLPW_MASK, (M) & VMULLPW_MASK)
|
||||
#define DO_VMULLPTW(N, M) DO_VMULLPBW((N) >> 16, (M) >> 16)
|
||||
|
||||
DO_2OP(vmullpbh, 8, uint64_t, DO_VMULLPBH)
|
||||
DO_2OP(vmullpth, 8, uint64_t, DO_VMULLPTH)
|
||||
DO_2OP(vmullpbw, 8, uint64_t, DO_VMULLPBW)
|
||||
DO_2OP(vmullptw, 8, uint64_t, DO_VMULLPTW)
|
||||
|
||||
/*
|
||||
* Because the computation type is at least twice as large as required,
|
||||
* these work for both signed and unsigned source types.
|
||||
|
@ -464,6 +464,34 @@ static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
|
||||
return do_2op(s, a, fns[a->size]);
|
||||
}
|
||||
|
||||
static bool trans_VMULLP_B(DisasContext *s, arg_2op *a)
|
||||
{
|
||||
/*
|
||||
* Note that a->size indicates the output size, ie VMULL.P8
|
||||
* is the 8x8->16 operation and a->size is MO_16; VMULL.P16
|
||||
* is the 16x16->32 operation and a->size is MO_32.
|
||||
*/
|
||||
static MVEGenTwoOpFn * const fns[] = {
|
||||
NULL,
|
||||
gen_helper_mve_vmullpbh,
|
||||
gen_helper_mve_vmullpbw,
|
||||
NULL,
|
||||
};
|
||||
return do_2op(s, a, fns[a->size]);
|
||||
}
|
||||
|
||||
static bool trans_VMULLP_T(DisasContext *s, arg_2op *a)
|
||||
{
|
||||
/* a->size is as for trans_VMULLP_B */
|
||||
static MVEGenTwoOpFn * const fns[] = {
|
||||
NULL,
|
||||
gen_helper_mve_vmullpth,
|
||||
gen_helper_mve_vmullptw,
|
||||
NULL,
|
||||
};
|
||||
return do_2op(s, a, fns[a->size]);
|
||||
}
|
||||
|
||||
/*
|
||||
* VADC and VSBC: these perform an add-with-carry or subtract-with-carry
|
||||
* of the 32-bit elements in each lane of the input vectors, where the
|
||||
|
@ -2028,11 +2028,23 @@ static uint64_t expand_byte_to_half(uint64_t x)
|
||||
| ((x & 0xff000000) << 24);
|
||||
}
|
||||
|
||||
static uint64_t pmull_h(uint64_t op1, uint64_t op2)
|
||||
uint64_t pmull_w(uint64_t op1, uint64_t op2)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
int i;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
uint64_t mask = (op1 & 0x0000000100000001ull) * 0xffffffff;
|
||||
result ^= op2 & mask;
|
||||
op1 >>= 1;
|
||||
op2 <<= 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint64_t pmull_h(uint64_t op1, uint64_t op2)
|
||||
{
|
||||
uint64_t result = 0;
|
||||
int i;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uint64_t mask = (op1 & 0x0001000100010001ull) * 0xffff;
|
||||
result ^= op2 & mask;
|
||||
|
@ -206,4 +206,15 @@ int16_t do_sqrdmlah_h(int16_t, int16_t, int16_t, bool, bool, uint32_t *);
|
||||
int32_t do_sqrdmlah_s(int32_t, int32_t, int32_t, bool, bool, uint32_t *);
|
||||
int64_t do_sqrdmlah_d(int64_t, int64_t, int64_t, bool, bool);
|
||||
|
||||
/*
|
||||
* 8 x 8 -> 16 vector polynomial multiply where the inputs are
|
||||
* in the low 8 bits of each 16-bit element
|
||||
*/
|
||||
uint64_t pmull_h(uint64_t op1, uint64_t op2);
|
||||
/*
|
||||
* 16 x 16 -> 32 vector polynomial multiply where the inputs are
|
||||
* in the low 16 bits of each 32-bit element
|
||||
*/
|
||||
uint64_t pmull_w(uint64_t op1, uint64_t op2);
|
||||
|
||||
#endif /* TARGET_ARM_VEC_INTERNALS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user