diff options
author | Peter Maydell | 2021-06-28 15:58:28 +0200 |
---|---|---|
committer | Peter Maydell | 2021-07-02 12:48:37 +0200 |
commit | 162e2655000689e44ac4c8e9e8dc413821e0adda (patch) | |
tree | cd96558436693fa9fd8676b8548f42c88bd1906a /target/arm | |
parent | target/arm: Implement MVE VSRI, VSLI (diff) | |
download | qemu-162e2655000689e44ac4c8e9e8dc413821e0adda.tar.gz qemu-162e2655000689e44ac4c8e9e8dc413821e0adda.tar.xz qemu-162e2655000689e44ac4c8e9e8dc413821e0adda.zip |
target/arm: Implement MVE VSHRN, VRSHRN
Implement the MVE shift-right-and-narrow insn VSHRN and VRSHRN.
do_urshr() is borrowed from sve_helper.c.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210628135835.6690-12-peter.maydell@linaro.org
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/helper-mve.h | 10 | ||||
-rw-r--r-- | target/arm/mve.decode | 11 | ||||
-rw-r--r-- | target/arm/mve_helper.c | 40 | ||||
-rw-r--r-- | target/arm/translate-mve.c | 15 |
4 files changed, 76 insertions, 0 deletions
diff --git a/target/arm/helper-mve.h b/target/arm/helper-mve.h index e452d2ef7a..323ac07fa3 100644 --- a/target/arm/helper-mve.h +++ b/target/arm/helper-mve.h @@ -404,3 +404,13 @@ DEF_HELPER_FLAGS_4(mve_vsriw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vslib, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vslih, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) DEF_HELPER_FLAGS_4(mve_vsliw, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(mve_vshrnbb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vshrnbh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vshrntb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vshrnth, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) + +DEF_HELPER_FLAGS_4(mve_vrshrnbb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vrshrnbh, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vrshrntb, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) +DEF_HELPER_FLAGS_4(mve_vrshrnth, TCG_CALL_NO_WG, void, env, ptr, ptr, i32) diff --git a/target/arm/mve.decode b/target/arm/mve.decode index c3b5366617..e2c177f56a 100644 --- a/target/arm/mve.decode +++ b/target/arm/mve.decode @@ -380,3 +380,14 @@ VSRI 111 1 1111 1 . ... ... ... 0 0100 0 1 . 1 ... 0 @2_shr_w VSLI 111 1 1111 1 . ... ... ... 0 0101 0 1 . 1 ... 0 @2_shl_b VSLI 111 1 1111 1 . ... ... ... 0 0101 0 1 . 1 ... 0 @2_shl_h VSLI 111 1 1111 1 . ... ... ... 0 0101 0 1 . 1 ... 0 @2_shl_w + +# Narrowing shifts (which only support b and h sizes) +VSHRNB 111 0 1110 1 . ... ... ... 0 1111 1 1 . 0 ... 1 @2_shr_b +VSHRNB 111 0 1110 1 . ... ... ... 0 1111 1 1 . 0 ... 1 @2_shr_h +VSHRNT 111 0 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 1 @2_shr_b +VSHRNT 111 0 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 1 @2_shr_h + +VRSHRNB 111 1 1110 1 . ... ... ... 0 1111 1 1 . 0 ... 1 @2_shr_b +VRSHRNB 111 1 1110 1 . ... ... ... 0 1111 1 1 . 0 ... 1 @2_shr_h +VRSHRNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 1 @2_shr_b +VRSHRNT 111 1 1110 1 . ... ... ... 1 1111 1 1 . 0 ... 1 @2_shr_h diff --git a/target/arm/mve_helper.c b/target/arm/mve_helper.c index 24336d1d28..a97942208b 100644 --- a/target/arm/mve_helper.c +++ b/target/arm/mve_helper.c @@ -1324,3 +1324,43 @@ DO_2SHIFT_INSERT(vsliw, 4, DO_SHL, SHL_MASK) DO_VSHLL_ALL(vshllb, false) DO_VSHLL_ALL(vshllt, true) + +/* + * Narrowing right shifts, taking a double sized input, shifting it + * and putting the result in either the top or bottom half of the output. + * ESIZE, TYPE are the output, and LESIZE, LTYPE the input. + */ +#define DO_VSHRN(OP, TOP, ESIZE, TYPE, LESIZE, LTYPE, FN) \ + void HELPER(glue(mve_, OP))(CPUARMState *env, void *vd, \ + void *vm, uint32_t shift) \ + { \ + LTYPE *m = vm; \ + TYPE *d = vd; \ + uint16_t mask = mve_element_mask(env); \ + unsigned le; \ + for (le = 0; le < 16 / LESIZE; le++, mask >>= LESIZE) { \ + TYPE r = FN(m[H##LESIZE(le)], shift); \ + mergemask(&d[H##ESIZE(le * 2 + TOP)], r, mask); \ + } \ + mve_advance_vpt(env); \ + } + +#define DO_VSHRN_ALL(OP, FN) \ + DO_VSHRN(OP##bb, false, 1, uint8_t, 2, uint16_t, FN) \ + DO_VSHRN(OP##bh, false, 2, uint16_t, 4, uint32_t, FN) \ + DO_VSHRN(OP##tb, true, 1, uint8_t, 2, uint16_t, FN) \ + DO_VSHRN(OP##th, true, 2, uint16_t, 4, uint32_t, FN) + +static inline uint64_t do_urshr(uint64_t x, unsigned sh) +{ + if (likely(sh < 64)) { + return (x >> sh) + ((x >> (sh - 1)) & 1); + } else if (sh == 64) { + return x >> 63; + } else { + return 0; + } +} + +DO_VSHRN_ALL(vshrn, DO_SHR) +DO_VSHRN_ALL(vrshrn, do_urshr) diff --git a/target/arm/translate-mve.c b/target/arm/translate-mve.c index b031f84966..f1a8f21b77 100644 --- a/target/arm/translate-mve.c +++ b/target/arm/translate-mve.c @@ -911,3 +911,18 @@ DO_VSHLL(VSHLL_BS, vshllbs) DO_VSHLL(VSHLL_BU, vshllbu) DO_VSHLL(VSHLL_TS, vshllts) DO_VSHLL(VSHLL_TU, vshlltu) + +#define DO_2SHIFT_N(INSN, FN) \ + static bool trans_##INSN(DisasContext *s, arg_2shift *a) \ + { \ + static MVEGenTwoOpShiftFn * const fns[] = { \ + gen_helper_mve_##FN##b, \ + gen_helper_mve_##FN##h, \ + }; \ + return do_2shift(s, a, fns[a->size], false); \ + } + +DO_2SHIFT_N(VSHRNB, vshrnb) +DO_2SHIFT_N(VSHRNT, vshrnt) +DO_2SHIFT_N(VRSHRNB, vrshrnb) +DO_2SHIFT_N(VRSHRNT, vrshrnt) |