Add V6_vcvt2_{hf_ub,hf_b,ub_hf,b_hf}, which differ from vcvt only in
element interleaving.Reviewed-by: Pierrick Bouvier <[email protected]> Reviewed-by: Marco Liebel <[email protected]> Signed-off-by: Brian Cain <[email protected]> --- tests/tcg/hexagon/check_rev_gating.c | 6 + tests/tcg/hexagon/fp_hvx_v79.c | 110 +++++++++++++++++++ target/hexagon/tag_rev_info.c.inc | 4 + target/hexagon/imported/mmvec/encode_ext.def | 4 + target/hexagon/imported/mmvec/ext.idef | 33 ++++++ tests/tcg/hexagon/meson.build | 2 + 6 files changed, 159 insertions(+) create mode 100644 tests/tcg/hexagon/fp_hvx_v79.c diff --git a/tests/tcg/hexagon/check_rev_gating.c b/tests/tcg/hexagon/check_rev_gating.c index 3a5ed9c71ca..529cae70d85 100644 --- a/tests/tcg/hexagon/check_rev_gating.c +++ b/tests/tcg/hexagon/check_rev_gating.c @@ -131,6 +131,10 @@ TRY_FUNC(v83_vsfadd, TRY_FUNC(v79hvx_vmerge_qf, ".word 0x1f01e0e2 /* v2 = vmerge(v0.x, v1.w) */\n") +TRY_FUNC(v79hvx_vcvt2_hf_ub, + ".word 0x1ed5e0e2 /* v3:2.hf = vcvt2(v0.ub) */\n") +TRY_FUNC(v79hvx_vcvt2_b_hf, + ".word 0x1ac1e0c2 /* v2.b = vcvt2(v0.hf, v1.hf) */\n") TRY_FUNC(v81hvx_veqhf, ".word 0x1f82c11c /* q0 = vcmp.eq(v1.hf, v2.hf) */\n") @@ -177,6 +181,8 @@ int main(void) assert(try_v83_vsfadd() == SIGILL); assert(try_v79hvx_vmerge_qf() == SIGILL); + assert(try_v79hvx_vcvt2_hf_ub() == SIGILL); + assert(try_v79hvx_vcvt2_b_hf() == SIGILL); assert(try_v81hvx_veqhf() == SIGILL); diff --git a/tests/tcg/hexagon/fp_hvx_v79.c b/tests/tcg/hexagon/fp_hvx_v79.c new file mode 100644 index 00000000000..2f6bbd7cf40 --- /dev/null +++ b/tests/tcg/hexagon/fp_hvx_v79.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +/* + * Tests for the HVX IEEE floating point instructions introduced in v79. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <inttypes.h> +#include <hexagon_types.h> +#include <hvx_hexagon_protos.h> + +int err; +#include "hvx_misc.h" +#include "hex_test.h" + +/* + * The vcvt2 instructions differ from vcvt in how elements are interleaved + * between the vectors of a pair or the sources: + * + * Vdd.v[0].hf[2*i] = OP(Vu.FROM[4*i]); + * Vdd.v[0].hf[2*i+1] = OP(Vu.FROM[4*i+2]); + * Vdd.v[1].hf[2*i] = OP(Vu.FROM[4*i+1]); + * Vdd.v[1].hf[2*i+1] = OP(Vu.FROM[4*i+3]); + * + * Vd.TO[4*i] = OP(Vu.hf[2*i]); + * Vd.TO[4*i+1] = OP(Vv.hf[2*i]); + * Vd.TO[4*i+2] = OP(Vu.hf[2*i+1]); + * Vd.TO[4*i+3] = OP(Vv.hf[2*i+1]); + */ +#define DEF_TEST_VCVT2_WIDEN(FROM, MUL, ADD) \ + static void test_vcvt2_hf_##FROM(void) \ + { \ + HVX_VectorPair *hvx_output = (HVX_VectorPair *)&output[0]; \ + HVX_Vector buffer; \ + memset(expect, 0, sizeof(expect)); \ + for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) { \ + ((MMVector *)&buffer)->FROM[i] = i * MUL + ADD; \ + expect[i % 2].hf[2 * (i / 4) + ((i % 4) / 2)] = \ + raw_hf((_Float16)(((MMVector *)&buffer)->FROM[i])); \ + } \ + *hvx_output = Q6_Whf_vcvt2_V##FROM(buffer); \ + check_output_hf(__LINE__, 2); \ + } + +DEF_TEST_VCVT2_WIDEN(ub, 3, 1) +DEF_TEST_VCVT2_WIDEN(b, 5, 7) + +static const struct { + uint16_t hf; + uint8_t ub; + int8_t b; +} cvt2_narrow_cases[] = { + { HF_QNaN, UINT8_MAX, INT8_MAX }, + { HF_SNaN, UINT8_MAX, INT8_MAX }, + { HF_QNaN_neg, UINT8_MAX, INT8_MAX }, + { HF_INF, UINT8_MAX, INT8_MAX }, + { HF_INF_neg, 0, INT8_MIN }, + { HF_zero, 0, 0 }, + { HF_zero_neg, 0, 0 }, + { HF_neg_two, 0, -2 }, + { HF_one, 1, 1 }, + { 0x3e00 /* 1.5 */, 2, 2 }, + { 0x4100 /* 2.5 */, 2, 2 }, + { 0x4300 /* 3.5 */, 4, 4 }, + { 0x5640 /* 100 */, 100, 100 }, + { 0x5a40 /* 200 */, 200, INT8_MAX }, + { 0x5c00 /* 256 */, UINT8_MAX, INT8_MAX }, + { 0xd640 /* -100 */, 0, -100 }, + { 0xda40 /* -200 */, 0, INT8_MIN }, +}; +#define NUM_CVT2_NARROW_CASES ARRAY_SIZE(cvt2_narrow_cases) + +#define DEF_TEST_VCVT2_NARROW(TO) \ + static void test_vcvt2_##TO##_hf(void) \ + { \ + HVX_Vector *hvx_output = (HVX_Vector *)&output[0]; \ + HVX_Vector buffers[2]; \ + memset(expect, 0, sizeof(expect)); \ + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) { \ + for (int s = 0; s < 2; s++) { \ + int c = (2 * j + s) % NUM_CVT2_NARROW_CASES; \ + ((MMVector *)&buffers[s])->hf[j] = cvt2_narrow_cases[c].hf; \ + expect[0].TO[4 * (j / 2) + 2 * (j % 2) + s] = \ + cvt2_narrow_cases[c].TO; \ + } \ + } \ + *hvx_output = Q6_V##TO##_vcvt2_VhfVhf(buffers[0], buffers[1]); \ + check_output_##TO(__LINE__, 1); \ + } + +DEF_TEST_VCVT2_NARROW(ub) +DEF_TEST_VCVT2_NARROW(b) + +int main(void) +{ + test_vcvt2_hf_ub(); + test_vcvt2_hf_b(); + test_vcvt2_ub_hf(); + test_vcvt2_b_hf(); + + puts(err ? "FAIL" : "PASS"); + return err ? 1 : 0; +} diff --git a/target/hexagon/tag_rev_info.c.inc b/target/hexagon/tag_rev_info.c.inc index da0b1a648cf..ea586e1613e 100644 --- a/target/hexagon/tag_rev_info.c.inc +++ b/target/hexagon/tag_rev_info.c.inc @@ -664,6 +664,10 @@ static const struct tag_rev_info tag_rev_info[XX_LAST_OPCODE] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, [V6_vconv_qf32_sf] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, + [V6_vcvt2_b_hf] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, + [V6_vcvt2_hf_b] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, + [V6_vcvt2_hf_ub] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, + [V6_vcvt2_ub_hf] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, [V6_vilog2_hf] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, [V6_vilog2_qf16] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, [V6_vilog2_qf32] = { .introduced = HEX_VER_V79, .removed = HEX_VER_NONE }, diff --git a/target/hexagon/imported/mmvec/encode_ext.def b/target/hexagon/imported/mmvec/encode_ext.def index 34e63b89743..9605e870a1e 100644 --- a/target/hexagon/imported/mmvec/encode_ext.def +++ b/target/hexagon/imported/mmvec/encode_ext.def @@ -846,12 +846,16 @@ DEF_ENC(V6_vcvt_sf_hf,"00011110--0-0100PP1uuuuu100ddddd") DEF_ENC(V6_vcvt_hf_sf,"00011111011vvvvvPP1uuuuu001ddddd") DEF_ENC(V6_vcvt_hf_ub,"00011110--0-0100PP1uuuuu001ddddd") DEF_ENC(V6_vcvt_hf_b,"00011110--0-0100PP1uuuuu010ddddd") +DEF_ENC(V6_vcvt2_hf_ub,"0001111011010101PP1uuuuu111ddddd") +DEF_ENC(V6_vcvt2_hf_b,"0001111011010101PP1uuuuu110ddddd") DEF_ENC(V6_vcvt_hf_uh,"00011110--0-0100PP1uuuuu101ddddd") DEF_ENC(V6_vcvt_hf_h,"00011110--0-0100PP1uuuuu111ddddd") DEF_ENC(V6_vcvt_uh_hf,"00011110--0--101PP1uuuuu000ddddd") DEF_ENC(V6_vcvt_h_hf,"00011110--0-0110PP1uuuuu000ddddd") DEF_ENC(V6_vcvt_ub_hf,"00011111110vvvvvPP1uuuuu101ddddd") DEF_ENC(V6_vcvt_b_hf,"00011111110vvvvvPP1uuuuu110ddddd") +DEF_ENC(V6_vcvt2_ub_hf,"00011010110vvvvvPP1uuuuu111ddddd") +DEF_ENC(V6_vcvt2_b_hf,"00011010110vvvvvPP1uuuuu110ddddd") /* IEEE FP vconv instructions */ DEF_ENC(V6_vconv_sf_w,"00011110--0--101PP1uuuuu011ddddd") diff --git a/target/hexagon/imported/mmvec/ext.idef b/target/hexagon/imported/mmvec/ext.idef index 3592930777e..b9a4858d0c1 100644 --- a/target/hexagon/imported/mmvec/ext.idef +++ b/target/hexagon/imported/mmvec/ext.idef @@ -3103,6 +3103,25 @@ ITERATOR_INSN_IEEE_FP_DOUBLE_16(32, vcvt_hf_b, "Vdd32.hf=vcvt(Vu32.b)", VddV.v[1].hf[2*i] = int64_to_float16_scalbn(VuV.b[4*i+2], float_round_nearest_even, 0); VddV.v[1].hf[2*i+1] = int64_to_float16_scalbn(VuV.b[4*i+3], float_round_nearest_even, 0)) +/* + * The vcvt2 variants differ from vcvt only in which source elements land in + * which half of the result pair: the even source bytes go to the first + * vector and the odd ones to the second. + */ +ITERATOR_INSN_IEEE_FP_DOUBLE_16(32, vcvt2_hf_ub, "Vdd32.hf=vcvt2(Vu32.ub)", + "Vector IEEE cvt2 from int: ub widen to hf", + VddV.v[0].hf[2*i] = uint64_to_float16_scalbn(VuV.ub[4*i], 0, &env->hvx_fp_status); + VddV.v[0].hf[2*i+1] = uint64_to_float16_scalbn(VuV.ub[4*i+2], 0, &env->hvx_fp_status); + VddV.v[1].hf[2*i] = uint64_to_float16_scalbn(VuV.ub[4*i+1], 0, &env->hvx_fp_status); + VddV.v[1].hf[2*i+1] = uint64_to_float16_scalbn(VuV.ub[4*i+3], 0, &env->hvx_fp_status)) + +ITERATOR_INSN_IEEE_FP_DOUBLE_16(32, vcvt2_hf_b, "Vdd32.hf=vcvt2(Vu32.b)", + "Vector IEEE cvt2 from int: b widen to hf", + VddV.v[0].hf[2*i] = int64_to_float16_scalbn(VuV.b[4*i], 0, &env->hvx_fp_status); + VddV.v[0].hf[2*i+1] = int64_to_float16_scalbn(VuV.b[4*i+2], 0, &env->hvx_fp_status); + VddV.v[1].hf[2*i] = int64_to_float16_scalbn(VuV.b[4*i+1], 0, &env->hvx_fp_status); + VddV.v[1].hf[2*i+1] = int64_to_float16_scalbn(VuV.b[4*i+3], 0, &env->hvx_fp_status)) + ITERATOR_INSN_IEEE_FP_DOUBLE_32(32, vcvt_sf_hf, "Vdd32.sf=vcvt(Vu32.hf)", "Vector IEEE cvt: hf widen to sf", VddV.v[0].sf[i] = f16_to_f32(VuV.hf[2*i]); @@ -3139,6 +3158,20 @@ ITERATOR_INSN_IEEE_FP_16_32(32, vcvt_b_hf, "Vd32.b=vcvt(Vu32.hf,Vv32.hf)", VdV.b[4*i+2] = float16_to_int8_scalbn(VvV.hf[2*i], float_round_nearest_even, 0, &env->hvx_fp_status); VdV.b[4*i+3] = float16_to_int8_scalbn(VvV.hf[2*i+1], float_round_nearest_even, 0, &env->hvx_fp_status)) +ITERATOR_INSN_IEEE_FP_16_32(32, vcvt2_ub_hf, "Vd32.ub=vcvt2(Vu32.hf,Vv32.hf)", + "Vector cvt2 to int: hf narrow to ub", + VdV.ub[4*i] = float16_to_uint8_scalbn(VuV.hf[2*i], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.ub[4*i+1] = float16_to_uint8_scalbn(VvV.hf[2*i], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.ub[4*i+2] = float16_to_uint8_scalbn(VuV.hf[2*i+1], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.ub[4*i+3] = float16_to_uint8_scalbn(VvV.hf[2*i+1], float_round_nearest_even, 0, &env->hvx_fp_status)) + +ITERATOR_INSN_IEEE_FP_16_32(32, vcvt2_b_hf, "Vd32.b=vcvt2(Vu32.hf,Vv32.hf)", + "Vector cvt2 to int: hf narrow to b", + VdV.b[4*i] = float16_to_int8_scalbn(VuV.hf[2*i], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.b[4*i+1] = float16_to_int8_scalbn(VvV.hf[2*i], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.b[4*i+2] = float16_to_int8_scalbn(VuV.hf[2*i+1], float_round_nearest_even, 0, &env->hvx_fp_status); + VdV.b[4*i+3] = float16_to_int8_scalbn(VvV.hf[2*i+1], float_round_nearest_even, 0, &env->hvx_fp_status)) + ITERATOR_INSN_SHIFT_SLOT_FLT(32, vconv_w_sf,"Vd32.w=Vu32.sf", "Vector conversion of sf32 format to int w", VdV.w[i] = conv_w_sf(VuV.sf[i], &env->hvx_fp_status)) diff --git a/tests/tcg/hexagon/meson.build b/tests/tcg/hexagon/meson.build index 2b924598640..c38d2bea84f 100644 --- a/tests/tcg/hexagon/meson.build +++ b/tests/tcg/hexagon/meson.build @@ -54,6 +54,8 @@ tests += { 'qemu_args': ['-cpu', 'v73,ieee-fp=false']}, 'fp_hvx_cvt.c': {'cflags': [cflags, '-mv73', '-mhvx', '-mhvx-ieee-fp']}, 'fp_hvx_cmp.c': {'cflags': [cflags, '-mv73', '-mhvx', '-mhvx-ieee-fp']}, + 'fp_hvx_v79.c': {'cflags': [cflags, '-mv79', '-mhvx', '-mhvx-ieee-fp'], + 'qemu_args': ['-cpu', 'v79']}, 'v81_hvx.c': {'cflags': [cflags, '-mv81', '-mhvx', '-mhvx-ieee-fp'], 'qemu_args': ['-cpu', 'v81']}, 'qfloat_v81.c': {'cflags': [cflags, '-mv81', '-mhvx', '-mhvx-ieee-fp'], -- 2.34.1
