From fc2622f660fea5355565a6734c74f68e65953ac8 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 15:40:49 -0700 Subject: Hexagon (target/hexagon) Add support for v68/v69/v71/v73 Add support for the ELF flags Move target/hexagon/cpu.[ch] to be v73 Change the compiler flag used by "make check-tcg" The decbin instruction is removed in Hexagon v73, so check the version before trying to compile the instruction. Signed-off-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230427224057.3766963-2-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 3 +++ tests/tcg/hexagon/misc.c | 12 ++++++++++++ 2 files changed, 15 insertions(+) (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 7c94db4..59b1b07 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -82,6 +82,9 @@ TESTS += $(HEX_TESTS) usr: usr.c $(CC) $(CFLAGS) -mv67t -O2 -Wno-inline-asm -Wno-expansion-to-defined $< -o $@ $(LDFLAGS) +# Build this test with -mv71 to exercise the CABAC instruction +misc: misc.c + $(CC) $(CFLAGS) -mv71 -O2 $< -o $@ $(LDFLAGS) scatter_gather: CFLAGS += -mhvx vector_add_int: CFLAGS += -mhvx -fvectorize hvx_misc: hvx_misc.c hvx_misc.h diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c index e126751..4fcbb22 100644 --- a/tests/tcg/hexagon/misc.c +++ b/tests/tcg/hexagon/misc.c @@ -18,6 +18,8 @@ #include #include +#define CORE_HAS_CABAC (__HEXAGON_ARCH__ <= 71) + typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; @@ -245,6 +247,7 @@ static void check(int val, int expect) } } +#if CORE_HAS_CABAC static void check64(long long val, long long expect) { if (val != expect) { @@ -252,6 +255,7 @@ static void check64(long long val, long long expect) err++; } } +#endif uint32_t init[10] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; uint32_t array[10]; @@ -286,6 +290,7 @@ static long long creg_pair(int x, int y) return retval; } +#if CORE_HAS_CABAC static long long decbin(long long x, long long y, int *pred) { long long retval; @@ -295,6 +300,7 @@ static long long decbin(long long x, long long y, int *pred) : "r"(x), "r"(y)); return retval; } +#endif /* Check that predicates are auto-and'ed in a packet */ static int auto_and(void) @@ -388,8 +394,10 @@ void test_count_trailing_zeros_ones(void) int main() { int res; +#if CORE_HAS_CABAC long long res64; int pred; +#endif memcpy(array, init, sizeof(array)); S4_storerhnew_rr(array, 4, 0xffff); @@ -505,6 +513,7 @@ int main() res = test_clrtnew(2, 7); check(res, 7); +#if CORE_HAS_CABAC res64 = decbin(0xf0f1f2f3f4f5f6f7LL, 0x7f6f5f4f3f2f1f0fLL, &pred); check64(res64, 0x357980003700010cLL); check(pred, 0); @@ -512,6 +521,9 @@ int main() res64 = decbin(0xfLL, 0x1bLL, &pred); check64(res64, 0x78000100LL); check(pred, 1); +#else + puts("Skipping cabac tests"); +#endif res = auto_and(); check(res, 0); -- cgit v1.1 From 860132e29543c6ab747745ceeed875593a355d1f Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 15:40:51 -0700 Subject: Hexagon (tests/tcg/hexagon) Add v68 scalar tests Signed-off-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230427224057.3766963-4-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 2 + tests/tcg/hexagon/v68_scalar.c | 186 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 188 insertions(+) create mode 100644 tests/tcg/hexagon/v68_scalar.c (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 59b1b07..b7529e2 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -76,6 +76,8 @@ HEX_TESTS += test_vminh HEX_TESTS += test_vpmpyh HEX_TESTS += test_vspliceb +HEX_TESTS += v68_scalar + TESTS += $(HEX_TESTS) # This test has to be compiled for the -mv67t target diff --git a/tests/tcg/hexagon/v68_scalar.c b/tests/tcg/hexagon/v68_scalar.c new file mode 100644 index 0000000..7a8adb1 --- /dev/null +++ b/tests/tcg/hexagon/v68_scalar.c @@ -0,0 +1,186 @@ +/* + * Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include + +/* + * Test the scalar core instructions that are new in v68 + */ + +int err; + +static int buffer32[] = { 1, 2, 3, 4 }; +static long long buffer64[] = { 5, 6, 7, 8 }; + +static void __check32(int line, uint32_t result, uint32_t expect) +{ + if (result != expect) { + printf("ERROR at line %d: 0x%08x != 0x%08x\n", + line, result, expect); + err++; + } +} + +#define check32(RES, EXP) __check32(__LINE__, RES, EXP) + +static void __check64(int line, uint64_t result, uint64_t expect) +{ + if (result != expect) { + printf("ERROR at line %d: 0x%016llx != 0x%016llx\n", + line, result, expect); + err++; + } +} + +#define check64(RES, EXP) __check64(__LINE__, RES, EXP) + +static inline int loadw_aq(int *p) +{ + int res; + asm volatile("%0 = memw_aq(%1)\n\t" + : "=r"(res) : "r"(p)); + return res; +} + +static void test_loadw_aq(void) +{ + int res; + + res = loadw_aq(&buffer32[0]); + check32(res, 1); + res = loadw_aq(&buffer32[1]); + check32(res, 2); +} + +static inline long long loadd_aq(long long *p) +{ + long long res; + asm volatile("%0 = memd_aq(%1)\n\t" + : "=r"(res) : "r"(p)); + return res; +} + +static void test_loadd_aq(void) +{ + long long res; + + res = loadd_aq(&buffer64[2]); + check64(res, 7); + res = loadd_aq(&buffer64[3]); + check64(res, 8); +} + +static inline void release_at(int *p) +{ + asm volatile("release(%0):at\n\t" + : : "r"(p)); +} + +static void test_release_at(void) +{ + release_at(&buffer32[2]); + check64(buffer32[2], 3); + release_at(&buffer32[3]); + check64(buffer32[3], 4); +} + +static inline void release_st(int *p) +{ + asm volatile("release(%0):st\n\t" + : : "r"(p)); +} + +static void test_release_st(void) +{ + release_st(&buffer32[2]); + check64(buffer32[2], 3); + release_st(&buffer32[3]); + check64(buffer32[3], 4); +} + +static inline void storew_rl_at(int *p, int val) +{ + asm volatile("memw_rl(%0):at = %1\n\t" + : : "r"(p), "r"(val) : "memory"); +} + +static void test_storew_rl_at(void) +{ + storew_rl_at(&buffer32[2], 9); + check64(buffer32[2], 9); + storew_rl_at(&buffer32[3], 10); + check64(buffer32[3], 10); +} + +static inline void stored_rl_at(long long *p, long long val) +{ + asm volatile("memd_rl(%0):at = %1\n\t" + : : "r"(p), "r"(val) : "memory"); +} + +static void test_stored_rl_at(void) +{ + stored_rl_at(&buffer64[2], 11); + check64(buffer64[2], 11); + stored_rl_at(&buffer64[3], 12); + check64(buffer64[3], 12); +} + +static inline void storew_rl_st(int *p, int val) +{ + asm volatile("memw_rl(%0):st = %1\n\t" + : : "r"(p), "r"(val) : "memory"); +} + +static void test_storew_rl_st(void) +{ + storew_rl_st(&buffer32[0], 13); + check64(buffer32[0], 13); + storew_rl_st(&buffer32[1], 14); + check64(buffer32[1], 14); +} + +static inline void stored_rl_st(long long *p, long long val) +{ + asm volatile("memd_rl(%0):st = %1\n\t" + : : "r"(p), "r"(val) : "memory"); +} + +static void test_stored_rl_st(void) +{ + stored_rl_st(&buffer64[0], 15); + check64(buffer64[0], 15); + stored_rl_st(&buffer64[1], 15); + check64(buffer64[1], 15); +} + +int main() +{ + test_loadw_aq(); + test_loadd_aq(); + test_release_at(); + test_release_st(); + test_storew_rl_at(); + test_stored_rl_at(); + test_storew_rl_st(); + test_stored_rl_st(); + + puts(err ? "FAIL" : "PASS"); + return err ? 1 : 0; +} -- cgit v1.1 From d636fb70b26ba2f712008a6deafeef55a8fd0a9c Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 15:40:53 -0700 Subject: Hexagon (tests/tcg/hexagon) Add v68 HVX tests Signed-off-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230427224057.3766963-6-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 3 + tests/tcg/hexagon/v68_hvx.c | 90 +++++++++++++++++++++ tests/tcg/hexagon/v6mpy_ref.c.inc | 161 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 tests/tcg/hexagon/v68_hvx.c create mode 100644 tests/tcg/hexagon/v6mpy_ref.c.inc (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index b7529e2..2ee930c 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -77,6 +77,7 @@ HEX_TESTS += test_vpmpyh HEX_TESTS += test_vspliceb HEX_TESTS += v68_scalar +HEX_TESTS += v68_hvx TESTS += $(HEX_TESTS) @@ -92,6 +93,8 @@ vector_add_int: CFLAGS += -mhvx -fvectorize hvx_misc: hvx_misc.c hvx_misc.h hvx_misc: CFLAGS += -mhvx hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant +v68_hvx: v68_hvx.c hvx_misc.h v6mpy_ref.c.inc +v68_hvx: CFLAGS += -mhvx -Wno-unused-function hvx_histogram: hvx_histogram.c hvx_histogram_row.S $(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS) diff --git a/tests/tcg/hexagon/v68_hvx.c b/tests/tcg/hexagon/v68_hvx.c new file mode 100644 index 0000000..0271872 --- /dev/null +++ b/tests/tcg/hexagon/v68_hvx.c @@ -0,0 +1,90 @@ +/* + * Copyright(c) 2022-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +int err; + +#include "hvx_misc.h" + +MMVector v6mpy_buffer0[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); +MMVector v6mpy_buffer1[BUFSIZE] __attribute__((aligned(MAX_VEC_SIZE_BYTES))); + +static void init_v6mpy_buffers(void) +{ + int counter0 = 0; + int counter1 = 17; + for (int i = 0; i < BUFSIZE; i++) { + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + v6mpy_buffer0[i].w[j] = counter0++; + v6mpy_buffer1[i].w[j] = counter1++; + } + } +} + +int v6mpy_ref[BUFSIZE][MAX_VEC_SIZE_BYTES / 4] = { +#include "v6mpy_ref.c.inc" +}; + +static void test_v6mpy(void) +{ + void *p00 = buffer0; + void *p01 = v6mpy_buffer0; + void *p10 = buffer1; + void *p11 = v6mpy_buffer1; + void *pout = output; + + memset(expect, 0xff, sizeof(expect)); + memset(output, 0xff, sizeof(expect)); + + for (int i = 0; i < BUFSIZE; i++) { + asm("v2 = vmem(%0 + #0)\n\t" + "v3 = vmem(%1 + #0)\n\t" + "v4 = vmem(%2 + #0)\n\t" + "v5 = vmem(%3 + #0)\n\t" + "v5:4.w = v6mpy(v5:4.ub, v3:2.b, #1):v\n\t" + "vmem(%4 + #0) = v4\n\t" + : : "r"(p00), "r"(p01), "r"(p10), "r"(p11), "r"(pout) + : "v2", "v3", "v4", "v5", "memory"); + p00 += sizeof(MMVector); + p01 += sizeof(MMVector); + p10 += sizeof(MMVector); + p11 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + expect[i].w[j] = v6mpy_ref[i][j]; + } + } + + check_output_w(__LINE__, BUFSIZE); +} + +int main() +{ + init_buffers(); + init_v6mpy_buffers(); + + test_v6mpy(); + + puts(err ? "FAIL" : "PASS"); + return err ? 1 : 0; +} diff --git a/tests/tcg/hexagon/v6mpy_ref.c.inc b/tests/tcg/hexagon/v6mpy_ref.c.inc new file mode 100644 index 0000000..8258cdd --- /dev/null +++ b/tests/tcg/hexagon/v6mpy_ref.c.inc @@ -0,0 +1,161 @@ +/* + * Copyright(c) 2021-2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +{ 0xffffee11, 0xfffffcca, 0xffffc1b3, 0xffffd0cc, + 0xffffe215, 0xfffff58e, 0xffffaf37, 0xffffc310, + 0xffffd919, 0xfffff152, 0xffff9fbb, 0xffffb854, + 0xffffd31d, 0xfffff016, 0xffff933f, 0xffffb098, + 0xffffd021, 0xfffff1da, 0xffff89c3, 0xffffabdc, + 0xffffd025, 0xfffff69e, 0xffff8347, 0xffffaa20, + 0xffffd329, 0xfffffe62, 0xffff7fcb, 0xffffab64, + 0xffffd92d, 0x00000926, 0xffff7f4f, 0xffffafa8, + }, +{ 0xffffe231, 0x000016ea, 0xffff81d3, 0xffffb6ec, + 0xffffee35, 0x000027ae, 0xffff8757, 0xffffc130, + 0xfffffd39, 0x00003b72, 0xffff8fdb, 0xffffce74, + 0x00000f3d, 0x00005236, 0xffff9b5f, 0xffffdeb8, + 0x00002441, 0x00006bfa, 0xffffa9e3, 0xfffff1fc, + 0x00003c45, 0x000088be, 0xffffbb67, 0x00000840, + 0x00005749, 0x0000a882, 0xffffcfeb, 0xffffe684, + 0x0000494d, 0x00009a46, 0xffffb16f, 0x000002c8, + }, +{ 0xfffff351, 0x0000440a, 0xffff4af3, 0xffff9c0c, + 0xffffef55, 0x000044ce, 0xffff4077, 0xffff9650, + 0xffffee59, 0x00004892, 0xffff38fb, 0xffff9394, + 0xfffff05d, 0x00004f56, 0xffff347f, 0xffff93d8, + 0xfffff561, 0x0000591a, 0xffff3303, 0xffff971c, + 0xfffffd65, 0x000065de, 0xffff3487, 0xffff9d60, + 0x00000869, 0x000075a2, 0xffff390b, 0xffffa6a4, + 0x0000166d, 0x00008866, 0xffff408f, 0xffffb2e8, + }, +{ 0x00002771, 0x00009e2a, 0xffff4b13, 0xffffc22c, + 0x00003b75, 0x0000b6ee, 0xffff5897, 0xffffd470, + 0x00005279, 0x0000d2b2, 0xffff691b, 0xffffe9b4, + 0x00006c7d, 0x0000f176, 0xffff7c9f, 0x000001f8, + 0x00008981, 0x0001133a, 0xffff9323, 0x00001d3c, + 0x0000a985, 0x000137fe, 0xffffaca7, 0x00003b80, + 0x0000cc89, 0x00015fc2, 0xffffc92b, 0xffffe1c4, + 0x0000868d, 0x00011986, 0xffff72af, 0x00000608, + }, +{ 0xfffff891, 0x00008b4a, 0xfffed433, 0xffff674c, + 0xfffffc95, 0x0000940e, 0xfffed1b7, 0xffff6990, + 0x00000399, 0x00009fd2, 0xfffed23b, 0xffff6ed4, + 0x00000d9d, 0x0000ae96, 0xfffed5bf, 0xffff7718, + 0x00001aa1, 0x0000c05a, 0xfffedc43, 0xffff825c, + 0x00002aa5, 0x0000d51e, 0xfffee5c7, 0xffff90a0, + 0x00003da9, 0x0000ece2, 0xfffef24b, 0xffffa1e4, + 0x000053ad, 0x000107a6, 0xffff01cf, 0xffffb628, + }, +{ 0x00006cb1, 0x0001256a, 0xffff1453, 0xffffcd6c, + 0x000088b5, 0x0001462e, 0xffff29d7, 0xffffe7b0, + 0x0000a7b9, 0x000169f2, 0xffff425b, 0x000004f4, + 0x0000c9bd, 0x000190b6, 0xffff5ddf, 0x00002538, + 0x0000eec1, 0x0001ba7a, 0xffff7c63, 0x0000487c, + 0x000116c5, 0x0001e73e, 0xffff9de7, 0x00006ec0, + 0x000141c9, 0x00021702, 0xffffc26b, 0xffffdd04, + 0x0000c3cd, 0x000198c6, 0xffff33ef, 0x00000948, + }, +{ 0xfffffdd1, 0x0000d28a, 0xfffe5d73, 0xffff328c, + 0x000009d5, 0x0000e34e, 0xfffe62f7, 0xffff3cd0, + 0x000018d9, 0x0000f712, 0xfffe6b7b, 0xffff4a14, + 0x00002add, 0x00010dd6, 0xfffe76ff, 0xffff5a58, + 0x00003fe1, 0x0001279a, 0xfffe8583, 0xffff6d9c, + 0x000057e5, 0x0001445e, 0xfffe9707, 0xffff83e0, + 0x000072e9, 0x00016422, 0xfffeab8b, 0xffff9d24, + 0x000090ed, 0x000186e6, 0xfffec30f, 0xffffb968, + }, +{ 0x0000b1f1, 0x0001acaa, 0xfffedd93, 0xffffd8ac, + 0x0000d5f5, 0x0001d56e, 0xfffefb17, 0xfffffaf0, + 0x0000fcf9, 0x00020132, 0xffff1b9b, 0x00002034, + 0x000126fd, 0x00022ff6, 0xffff3f1f, 0x00008b36, + 0x000093c3, 0x00009d80, 0x00009d6d, 0x0000a78a, + 0x0000b4d7, 0x0000c354, 0x0000b801, 0x0000c6de, + 0x0000d4eb, 0x0000e828, 0x0000d195, 0xffffea32, + 0x00000fff, 0x000022fc, 0xfffffc29, 0x00000f86, + }, +{ 0xffffee13, 0xfffffcd0, 0xffffc1bd, 0xffffd0da, + 0xffffe327, 0xfffff6a4, 0xffffb051, 0xffffc42e, + 0xffffd73b, 0xffffef78, 0xffff9de5, 0xffffb682, + 0xffffd24f, 0xffffef4c, 0xffff9279, 0xffffafd6, + 0xffffd063, 0xfffff220, 0xffff8a0d, 0xffffac2a, + 0xffffd177, 0xfffff7f4, 0xffff84a1, 0xffffab7e, + 0xffffd18b, 0xfffffcc8, 0xffff7e35, 0xffffa9d2, + 0xffffd89f, 0x0000089c, 0xffff7ec9, 0xffffaf26, + }, +{ 0xffffe2b3, 0x00001770, 0xffff825d, 0xffffb77a, + 0xffffefc7, 0x00002944, 0xffff88f1, 0xffffc2ce, + 0xfffffbdb, 0x00003a18, 0xffff8e85, 0xffffcd22, + 0x00000eef, 0x000051ec, 0xffff9b19, 0xffffde76, + 0x00002503, 0x00006cc0, 0xffffaaad, 0xfffff2ca, + 0x00003e17, 0x00008a94, 0xffffbd41, 0x00000a1e, + 0x0000562b, 0x0000a768, 0xffffced5, 0xffffe572, + 0x0000493f, 0x00009a3c, 0xffffb169, 0x000002c6, + }, +{ 0xfffff353, 0x00004410, 0xffff4afd, 0xffff9c1a, + 0xfffff067, 0x000045e4, 0xffff4191, 0xffff976e, + 0xffffec7b, 0x000046b8, 0xffff3725, 0xffff91c2, + 0xffffef8f, 0x00004e8c, 0xffff33b9, 0xffff9316, + 0xfffff5a3, 0x00005960, 0xffff334d, 0xffff976a, + 0xfffffeb7, 0x00006734, 0xffff35e1, 0xffff9ebe, + 0x000006cb, 0x00007408, 0xffff3775, 0xffffa512, + 0x000015df, 0x000087dc, 0xffff4009, 0xffffb266, + }, +{ 0x000027f3, 0x00009eb0, 0xffff4b9d, 0xffffc2ba, + 0x00003d07, 0x0000b884, 0xffff5a31, 0xffffd60e, + 0x0000511b, 0x0000d158, 0xffff67c5, 0xffffe862, + 0x00006c2f, 0x0000f12c, 0xffff7c59, 0x000001b6, + 0x00008a43, 0x00011400, 0xffff93ed, 0x00001e0a, + 0x0000ab57, 0x000139d4, 0xffffae81, 0x00003d5e, + 0x0000cb6b, 0x00015ea8, 0xffffc815, 0xffffe0b2, + 0x0000867f, 0x0001197c, 0xffff72a9, 0x00000606, + }, +{ 0xfffff893, 0x00008b50, 0xfffed43d, 0xffff675a, + 0xfffffda7, 0x00009524, 0xfffed2d1, 0xffff6aae, + 0x000001bb, 0x00009df8, 0xfffed065, 0xffff6d02, + 0x00000ccf, 0x0000adcc, 0xfffed4f9, 0xffff7656, + 0x00001ae3, 0x0000c0a0, 0xfffedc8d, 0xffff82aa, + 0x00002bf7, 0x0000d674, 0xfffee721, 0xffff91fe, + 0x00003c0b, 0x0000eb48, 0xfffef0b5, 0xffffa052, + 0x0000531f, 0x0001071c, 0xffff0149, 0xffffb5a6, + }, +{ 0x00006d33, 0x000125f0, 0xffff14dd, 0xffffcdfa, + 0x00008a47, 0x000147c4, 0xffff2b71, 0xffffe94e, + 0x0000a65b, 0x00016898, 0xffff4105, 0x000003a2, + 0x0000c96f, 0x0001906c, 0xffff5d99, 0x000024f6, + 0x0000ef83, 0x0001bb40, 0xffff7d2d, 0x0000494a, + 0x00011897, 0x0001e914, 0xffff9fc1, 0x0000709e, + 0x000140ab, 0x000215e8, 0xffffc155, 0xffffdbf2, + 0x0000c3bf, 0x000198bc, 0xffff33e9, 0x00000946, + }, +{ 0xfffffdd3, 0x0000d290, 0xfffe5d7d, 0xffff329a, + 0x00000ae7, 0x0000e464, 0xfffe6411, 0xffff3dee, + 0x000016fb, 0x0000f538, 0xfffe69a5, 0xffff4842, + 0x00002a0f, 0x00010d0c, 0xfffe7639, 0xffff5996, + 0x00004023, 0x000127e0, 0xfffe85cd, 0xffff6dea, + 0x00005937, 0x000145b4, 0xfffe9861, 0xffff853e, + 0x0000714b, 0x00016288, 0xfffea9f5, 0xffff9b92, + 0x0000905f, 0x0001865c, 0xfffec289, 0xffffb8e6, + }, +{ 0x0000b273, 0x0001ad30, 0xfffede1d, 0xffffd93a, + 0x0000d787, 0x0001d704, 0xfffefcb1, 0xfffffc8e, + 0x0000fb9b, 0x0001ffd8, 0xffff1a45, 0x00001ee2, + 0x000126af, 0x00022fac, 0xffff3ed9, 0x00008af4, + 0x00009485, 0x00009e46, 0x00009e37, 0x0000a858, + 0x0000b6a9, 0x0000c52a, 0x0000b9db, 0x0000c8bc, + 0x0000d3cd, 0x0000e70e, 0x0000d07f, 0xffffe920, + 0x00000ff1, 0x000022f2, 0xfffffc23, 0x00000f84, + }, -- cgit v1.1 From 6c61d4e138a3fb67ca443bb8017ac4049d5457a2 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 15:40:55 -0700 Subject: Hexagon (tests/tcg/hexagon) Add v69 HVX tests The following instructions are tested V6_vasrvuhubrndsat V6_vasrvuhubsat V6_vasrvwuhrndsat V6_vasrvwuhsat V6_vassign_tmp V6_vcombine_tmp V6_vmpyuhvs Signed-off-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230427224057.3766963-8-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 3 + tests/tcg/hexagon/v69_hvx.c | 318 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 321 insertions(+) create mode 100644 tests/tcg/hexagon/v69_hvx.c (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 2ee930c..558c056 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -78,6 +78,7 @@ HEX_TESTS += test_vspliceb HEX_TESTS += v68_scalar HEX_TESTS += v68_hvx +HEX_TESTS += v69_hvx TESTS += $(HEX_TESTS) @@ -95,6 +96,8 @@ hvx_misc: CFLAGS += -mhvx hvx_histogram: CFLAGS += -mhvx -Wno-gnu-folding-constant v68_hvx: v68_hvx.c hvx_misc.h v6mpy_ref.c.inc v68_hvx: CFLAGS += -mhvx -Wno-unused-function +v69_hvx: v69_hvx.c hvx_misc.h +v69_hvx: CFLAGS += -mhvx -Wno-unused-function hvx_histogram: hvx_histogram.c hvx_histogram_row.S $(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS) diff --git a/tests/tcg/hexagon/v69_hvx.c b/tests/tcg/hexagon/v69_hvx.c new file mode 100644 index 0000000..a0d567d --- /dev/null +++ b/tests/tcg/hexagon/v69_hvx.c @@ -0,0 +1,318 @@ +/* + * Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +int err; + +#include "hvx_misc.h" + +#define fVROUND(VAL, SHAMT) \ + ((VAL) + (((SHAMT) > 0) ? (1LL << ((SHAMT) - 1)) : 0)) + +#define fVSATUB(VAL) \ + ((((VAL) & 0xffLL) == (VAL)) ? \ + (VAL) : \ + ((((int32_t)(VAL)) < 0) ? 0 : 0xff)) + +#define fVSATUH(VAL) \ + ((((VAL) & 0xffffLL) == (VAL)) ? \ + (VAL) : \ + ((((int32_t)(VAL)) < 0) ? 0 : 0xffff)) + +static void test_vasrvuhubrndsat(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE / 2; i++) { + asm("v4 = vmem(%0 + #0)\n\t" + "v5 = vmem(%0 + #1)\n\t" + "v6 = vmem(%1 + #0)\n\t" + "v5.ub = vasr(v5:4.uh, v6.ub):rnd:sat\n\t" + "vmem(%2) = v5\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "v4", "v5", "v6", "memory"); + p0 += sizeof(MMVector) * 2; + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) { + int shamt; + uint8_t byte0; + uint8_t byte1; + + shamt = buffer1[i].ub[2 * j + 0] & 0x7; + byte0 = fVSATUB(fVROUND(buffer0[2 * i + 0].uh[j], shamt) >> shamt); + shamt = buffer1[i].ub[2 * j + 1] & 0x7; + byte1 = fVSATUB(fVROUND(buffer0[2 * i + 1].uh[j], shamt) >> shamt); + expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff); + } + } + + check_output_h(__LINE__, BUFSIZE / 2); +} + +static void test_vasrvuhubsat(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE / 2; i++) { + asm("v4 = vmem(%0 + #0)\n\t" + "v5 = vmem(%0 + #1)\n\t" + "v6 = vmem(%1 + #0)\n\t" + "v5.ub = vasr(v5:4.uh, v6.ub):sat\n\t" + "vmem(%2) = v5\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "v4", "v5", "v6", "memory"); + p0 += sizeof(MMVector) * 2; + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) { + int shamt; + uint8_t byte0; + uint8_t byte1; + + shamt = buffer1[i].ub[2 * j + 0] & 0x7; + byte0 = fVSATUB(buffer0[2 * i + 0].uh[j] >> shamt); + shamt = buffer1[i].ub[2 * j + 1] & 0x7; + byte1 = fVSATUB(buffer0[2 * i + 1].uh[j] >> shamt); + expect[i].uh[j] = (byte1 << 8) | (byte0 & 0xff); + } + } + + check_output_h(__LINE__, BUFSIZE / 2); +} + +static void test_vasrvwuhrndsat(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE / 2; i++) { + asm("v4 = vmem(%0 + #0)\n\t" + "v5 = vmem(%0 + #1)\n\t" + "v6 = vmem(%1 + #0)\n\t" + "v5.uh = vasr(v5:4.w, v6.uh):rnd:sat\n\t" + "vmem(%2) = v5\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "v4", "v5", "v6", "memory"); + p0 += sizeof(MMVector) * 2; + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + int shamt; + uint16_t half0; + uint16_t half1; + + shamt = buffer1[i].uh[2 * j + 0] & 0xf; + half0 = fVSATUH(fVROUND(buffer0[2 * i + 0].w[j], shamt) >> shamt); + shamt = buffer1[i].uh[2 * j + 1] & 0xf; + half1 = fVSATUH(fVROUND(buffer0[2 * i + 1].w[j], shamt) >> shamt); + expect[i].w[j] = (half1 << 16) | (half0 & 0xffff); + } + } + + check_output_w(__LINE__, BUFSIZE / 2); +} + +static void test_vasrvwuhsat(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE / 2; i++) { + asm("v4 = vmem(%0 + #0)\n\t" + "v5 = vmem(%0 + #1)\n\t" + "v6 = vmem(%1 + #0)\n\t" + "v5.uh = vasr(v5:4.w, v6.uh):sat\n\t" + "vmem(%2) = v5\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "v4", "v5", "v6", "memory"); + p0 += sizeof(MMVector) * 2; + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + int shamt; + uint16_t half0; + uint16_t half1; + + shamt = buffer1[i].uh[2 * j + 0] & 0xf; + half0 = fVSATUH(buffer0[2 * i + 0].w[j] >> shamt); + shamt = buffer1[i].uh[2 * j + 1] & 0xf; + half1 = fVSATUH(buffer0[2 * i + 1].w[j] >> shamt); + expect[i].w[j] = (half1 << 16) | (half0 & 0xffff); + } + } + + check_output_w(__LINE__, BUFSIZE / 2); +} + +static void test_vassign_tmp(void) +{ + void *p0 = buffer0; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE; i++) { + /* + * Assign into v12 as .tmp, then use it in the next packet + * Should get the new value within the same packet and + * the old value in the next packet + */ + asm("v3 = vmem(%0 + #0)\n\t" + "r1 = #1\n\t" + "v12 = vsplat(r1)\n\t" + "r1 = #2\n\t" + "v13 = vsplat(r1)\n\t" + "{\n\t" + " v12.tmp = v13\n\t" + " v4.w = vadd(v12.w, v3.w)\n\t" + "}\n\t" + "v4.w = vadd(v4.w, v12.w)\n\t" + "vmem(%1 + #0) = v4\n\t" + : : "r"(p0), "r"(pout) + : "r1", "v3", "v4", "v12", "v13", "memory"); + p0 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + expect[i].w[j] = buffer0[i].w[j] + 3; + } + } + + check_output_w(__LINE__, BUFSIZE); +} + +static void test_vcombine_tmp(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE; i++) { + /* + * Combine into v13:12 as .tmp, then use it in the next packet + * Should get the new value within the same packet and + * the old value in the next packet + */ + asm("v3 = vmem(%0 + #0)\n\t" + "r1 = #1\n\t" + "v12 = vsplat(r1)\n\t" + "r1 = #2\n\t" + "v13 = vsplat(r1)\n\t" + "r1 = #3\n\t" + "v14 = vsplat(r1)\n\t" + "r1 = #4\n\t" + "v15 = vsplat(r1)\n\t" + "{\n\t" + " v13:12.tmp = vcombine(v15, v14)\n\t" + " v4.w = vadd(v12.w, v3.w)\n\t" + " v16 = v13\n\t" + "}\n\t" + "v4.w = vadd(v4.w, v12.w)\n\t" + "v4.w = vadd(v4.w, v13.w)\n\t" + "v4.w = vadd(v4.w, v16.w)\n\t" + "vmem(%2 + #0) = v4\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "r1", "v3", "v4", "v12", "v13", "v14", "v15", "v16", "memory"); + p0 += sizeof(MMVector); + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + expect[i].w[j] = buffer0[i].w[j] + 10; + } + } + + check_output_w(__LINE__, BUFSIZE); +} + +static void test_vmpyuhvs(void) +{ + void *p0 = buffer0; + void *p1 = buffer1; + void *pout = output; + + memset(expect, 0xaa, sizeof(expect)); + memset(output, 0xbb, sizeof(output)); + + for (int i = 0; i < BUFSIZE; i++) { + asm("v4 = vmem(%0 + #0)\n\t" + "v5 = vmem(%1 + #0)\n\t" + "v4.uh = vmpy(V4.uh, v5.uh):>>16\n\t" + "vmem(%2) = v4\n\t" + : : "r"(p0), "r"(p1), "r"(pout) + : "v4", "v5", "memory"); + p0 += sizeof(MMVector); + p1 += sizeof(MMVector); + pout += sizeof(MMVector); + + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 2; j++) { + expect[i].uh[j] = (buffer0[i].uh[j] * buffer1[i].uh[j]) >> 16; + } + } + + check_output_h(__LINE__, BUFSIZE); +} + +int main() +{ + init_buffers(); + + test_vasrvuhubrndsat(); + test_vasrvuhubsat(); + test_vasrvwuhrndsat(); + test_vasrvwuhsat(); + + test_vassign_tmp(); + test_vcombine_tmp(); + + test_vmpyuhvs(); + + puts(err ? "FAIL" : "PASS"); + return err ? 1 : 0; +} -- cgit v1.1 From 4dd311ed2ee695a86ea77281c20dbeb115403d21 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 15:40:57 -0700 Subject: Hexagon (tests/tcg/hexagon) Add v73 scalar tests Tests added for the following instructions J2_callrh J2_jumprh Signed-off-by: Taylor Simpson Reviewed-by: Anton Johansson Message-Id: <20230427224057.3766963-10-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 2 + tests/tcg/hexagon/v73_scalar.c | 96 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 tests/tcg/hexagon/v73_scalar.c (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 558c056..3172f2e 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -79,6 +79,7 @@ HEX_TESTS += test_vspliceb HEX_TESTS += v68_scalar HEX_TESTS += v68_hvx HEX_TESTS += v69_hvx +HEX_TESTS += v73_scalar TESTS += $(HEX_TESTS) @@ -98,6 +99,7 @@ v68_hvx: v68_hvx.c hvx_misc.h v6mpy_ref.c.inc v68_hvx: CFLAGS += -mhvx -Wno-unused-function v69_hvx: v69_hvx.c hvx_misc.h v69_hvx: CFLAGS += -mhvx -Wno-unused-function +v73_scalar: CFLAGS += -Wno-unused-function hvx_histogram: hvx_histogram.c hvx_histogram_row.S $(CC) $(CFLAGS) $(CROSS_CC_GUEST_CFLAGS) $^ -o $@ $(LDFLAGS) diff --git a/tests/tcg/hexagon/v73_scalar.c b/tests/tcg/hexagon/v73_scalar.c new file mode 100644 index 0000000..fee67fc --- /dev/null +++ b/tests/tcg/hexagon/v73_scalar.c @@ -0,0 +1,96 @@ +/* + * Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include +#include +#include + +/* + * Test the scalar core instructions that are new in v73 + */ + +int err; + +static void __check32(int line, uint32_t result, uint32_t expect) +{ + if (result != expect) { + printf("ERROR at line %d: 0x%08x != 0x%08x\n", + line, result, expect); + err++; + } +} + +#define check32(RES, EXP) __check32(__LINE__, RES, EXP) + +static void __check64(int line, uint64_t result, uint64_t expect) +{ + if (result != expect) { + printf("ERROR at line %d: 0x%016llx != 0x%016llx\n", + line, result, expect); + err++; + } +} + +#define check64(RES, EXP) __check64(__LINE__, RES, EXP) + +static bool my_func_called; + +static void my_func(void) +{ + my_func_called = true; +} + +static inline void callrh(void *func) +{ + asm volatile("callrh %0\n\t" + : : "r"(func) + /* Mark the caller-save registers as clobbered */ + : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", + "r10", "r11", "r12", "r13", "r14", "r15", "r28", + "p0", "p1", "p2", "p3"); +} + +static void test_callrh(void) +{ + my_func_called = false; + callrh(&my_func); + check32(my_func_called, true); +} + +static void test_jumprh(void) +{ + uint32_t res; + asm ("%0 = #5\n\t" + "r0 = ##1f\n\t" + "jumprh r0\n\t" + "%0 = #3\n\t" + "jump 2f\n\t" + "1:\n\t" + "%0 = #1\n\t" + "2:\n\t" + : "=r"(res) : : "r0"); + check32(res, 1); +} + +int main() +{ + test_callrh(); + test_jumprh(); + + puts(err ? "FAIL" : "PASS"); + return err ? 1 : 0; +} -- cgit v1.1 From d05d5eebc77f607f96e582527e43908a274b2abf Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 16:00:05 -0700 Subject: Hexagon (target/hexagon) Short-circuit more HVX single instruction packets The generated helpers for HVX use pass-by-reference, so they can't short-circuit when the reads/writes overlap. The instructions with overrides are OK because they use tcg_gen_gvec_*. We add a flag has_hvx_helper to DisasContext and extend gen_analyze_funcs to set the flag when the instruction is an HVX instruction with a generated helper. We add an override for V6_vcombine so that it can be short-circuited along with a test case in tests/tcg/hexagon/hvx_misc.c Signed-off-by: Taylor Simpson Reviewed-by: Richard Henderson Message-Id: <20230427230012.3800327-15-tsimpson@quicinc.com> --- tests/tcg/hexagon/hvx_misc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'tests') diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c index d0e64e0..c89fe02 100644 --- a/tests/tcg/hexagon/hvx_misc.c +++ b/tests/tcg/hexagon/hvx_misc.c @@ -454,6 +454,25 @@ static void test_load_cur_predicated(void) check_output_w(__LINE__, BUFSIZE); } +static void test_vcombine(void) +{ + for (int i = 0; i < BUFSIZE / 2; i++) { + asm volatile("v2 = vsplat(%0)\n\t" + "v3 = vsplat(%1)\n\t" + "v3:2 = vcombine(v2, v3)\n\t" + "vmem(%2+#0) = v2\n\t" + "vmem(%2+#1) = v3\n\t" + : + : "r"(2 * i), "r"(2 * i + 1), "r"(&output[2 * i]) + : "v2", "v3", "memory"); + for (int j = 0; j < MAX_VEC_SIZE_BYTES / 4; j++) { + expect[2 * i].w[j] = 2 * i + 1; + expect[2 * i + 1].w[j] = 2 * i; + } + } + check_output_w(__LINE__, BUFSIZE); +} + int main() { init_buffers(); @@ -494,6 +513,8 @@ int main() test_load_tmp_predicated(); test_load_cur_predicated(); + test_vcombine(); + puts(err ? "FAIL" : "PASS"); return err ? 1 : 0; } -- cgit v1.1 From 00e64fda061ba65668a19dd1ea79e2a2f72090da Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Thu, 27 Apr 2023 16:00:06 -0700 Subject: Hexagon (target/hexagon) Add overrides for disabled idef-parser insns The following have overrides S2_insert S2_insert_rp S2_asr_r_svw_trun A2_swiz These instructions have semantics that write to the destination before all the operand reads have been completed. Therefore, the idef-parser versions were disabled with the short-circuit patch. Test cases added to tests/tcg/hexagon/read_write_overlap.c Signed-off-by: Taylor Simpson Reviewed-by: Richard Henderson Message-Id: <20230427230012.3800327-16-tsimpson@quicinc.com> --- tests/tcg/hexagon/Makefile.target | 1 + tests/tcg/hexagon/read_write_overlap.c | 136 +++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) create mode 100644 tests/tcg/hexagon/read_write_overlap.c (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 3172f2e..6109a7e 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -45,6 +45,7 @@ HEX_TESTS += fpstuff HEX_TESTS += overflow HEX_TESTS += signal_context HEX_TESTS += reg_mut +HEX_TESTS += read_write_overlap HEX_TESTS += vector_add_int HEX_TESTS += scatter_gather HEX_TESTS += hvx_misc diff --git a/tests/tcg/hexagon/read_write_overlap.c b/tests/tcg/hexagon/read_write_overlap.c new file mode 100644 index 0000000..a75fc11 --- /dev/null +++ b/tests/tcg/hexagon/read_write_overlap.c @@ -0,0 +1,136 @@ +/* + * Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +/* + * Test instructions where the semantics write to the destination + * before all the operand reads have been completed. + * + * These instructions are problematic when we short-circuit the + * register writes because the destination and source operands could + * be the same TCGv. + * + * We test by forcing the read and write to be register r7. + */ + +#include +#include +#include + +int err; + +static void __check(const char *filename, int line, int x, int expect) +{ + if (x != expect) { + printf("ERROR %s:%d - 0x%08x != 0x%08x\n", + filename, line, x, expect); + err++; + } +} + +#define check(x, expect) __check(__FILE__, __LINE__, (x), (expect)) + +#define insert(RES, X, WIDTH, OFFSET) \ + asm("r7 = %1\n\t" \ + "r7 = insert(r7, #" #WIDTH ", #" #OFFSET ")\n\t" \ + "%0 = r7\n\t" \ + : "=r"(RES) : "r"(X) : "r7") + +static void test_insert(void) +{ + uint32_t res; + + insert(res, 0x12345678, 8, 1); + check(res, 0x123456f0); + insert(res, 0x12345678, 0, 1); + check(res, 0x12345678); + insert(res, 0x12345678, 20, 16); + check(res, 0x56785678); +} + +static inline uint32_t insert_rp(uint32_t x, uint32_t width, uint32_t offset) +{ + uint64_t width_offset = (uint64_t)width << 32 | offset; + uint32_t res; + asm("r7 = %1\n\t" + "r7 = insert(r7, %2)\n\t" + "%0 = r7\n\t" + : "=r"(res) : "r"(x), "r"(width_offset) : "r7"); + return res; + +} + +static void test_insert_rp(void) +{ + check(insert_rp(0x12345678, 8, 1), 0x123456f0); + check(insert_rp(0x12345678, 63, 8), 0x34567878); + check(insert_rp(0x12345678, 127, 8), 0x34567878); + check(insert_rp(0x12345678, 8, 24), 0x78345678); + check(insert_rp(0x12345678, 8, 63), 0x12345678); + check(insert_rp(0x12345678, 8, 64), 0x00000000); +} + +static inline uint32_t asr_r_svw_trun(uint64_t x, uint32_t y) +{ + uint32_t res; + asm("r7 = %2\n\t" + "r7 = vasrw(%1, r7)\n\t" + "%0 = r7\n\t" + : "=r"(res) : "r"(x), "r"(y) : "r7"); + return res; +} + +static void test_asr_r_svw_trun(void) +{ + check(asr_r_svw_trun(0x1111111122222222ULL, 5), + 0x88881111); + check(asr_r_svw_trun(0x1111111122222222ULL, 63), + 0x00000000); + check(asr_r_svw_trun(0x1111111122222222ULL, 64), + 0x00000000); + check(asr_r_svw_trun(0x1111111122222222ULL, 127), + 0x22224444); + check(asr_r_svw_trun(0x1111111122222222ULL, 128), + 0x11112222); + check(asr_r_svw_trun(0xffffffff22222222ULL, 128), + 0xffff2222); +} + +static inline uint32_t swiz(uint32_t x) +{ + uint32_t res; + asm("r7 = %1\n\t" + "r7 = swiz(r7)\n\t" + "%0 = r7\n\t" + : "=r"(res) : "r"(x) : "r7"); + return res; +} + +static void test_swiz(void) +{ + check(swiz(0x11223344), 0x44332211); +} + +int main() +{ + test_insert(); + test_insert_rp(); + test_asr_r_svw_trun(); + test_swiz(); + + puts(err ? "FAIL" : "PASS"); + return err ? EXIT_FAILURE : EXIT_SUCCESS; +} -- cgit v1.1 From 163e5fa38e47281f8e83946794f6c202749bff32 Mon Sep 17 00:00:00 2001 From: Taylor Simpson Date: Wed, 26 Apr 2023 10:32:32 -0700 Subject: Hexagon (target/hexagon) Additional instructions handled by idef-parser **** Changes in v3 **** Fix bugs exposed by dpmpyss_rnd_s0 instruction Set correct size/signedness for constants Test cases added to tests/tcg/hexagon/misc.c **** Changes in v2 **** Fix bug in imm_print identified in clang build Currently, idef-parser skips all floating point instructions. However, there are some floating point instructions that can be handled. The following instructions are now parsed F2_sfimm_p F2_sfimm_n F2_dfimm_p F2_dfimm_n F2_dfmpyll F2_dfmpylh To make these instructions work, we fix some bugs in parser-helpers.c gen_rvalue_extend gen_cast_op imm_print lexer properly sets size/signedness of constants Test cases added to tests/tcg/hexagon/fpstuff.c Signed-off-by: Taylor Simpson Tested-by: Anton Johansson Reviewed-by: Anton Johansson Message-Id: <20230501203125.4025991-1-tsimpson@quicinc.com> --- tests/tcg/hexagon/fpstuff.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ tests/tcg/hexagon/misc.c | 35 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) (limited to 'tests') diff --git a/tests/tcg/hexagon/fpstuff.c b/tests/tcg/hexagon/fpstuff.c index 90ce9a6..28f9397 100644 --- a/tests/tcg/hexagon/fpstuff.c +++ b/tests/tcg/hexagon/fpstuff.c @@ -20,6 +20,7 @@ */ #include +#include const int FPINVF_BIT = 1; /* Invalid */ const int FPINVF = 1 << FPINVF_BIT; @@ -706,6 +707,57 @@ static void check_float2int_convs() check_fpstatus(usr, FPINVF); } +static void check_float_consts(void) +{ + int res32; + unsigned long long res64; + + asm("%0 = sfmake(#%1):neg\n\t" : "=r"(res32) : "i"(0xf)); + check32(res32, 0xbc9e0000); + + asm("%0 = sfmake(#%1):pos\n\t" : "=r"(res32) : "i"(0xf)); + check32(res32, 0x3c9e0000); + + asm("%0 = dfmake(#%1):neg\n\t" : "=r"(res64) : "i"(0xf)); + check64(res64, 0xbf93c00000000000ULL); + + asm("%0 = dfmake(#%1):pos\n\t" : "=r"(res64) : "i"(0xf)); + check64(res64, 0x3f93c00000000000ULL); +} + +static inline unsigned long long dfmpyll(double x, double y) +{ + unsigned long long res64; + asm("%0 = dfmpyll(%1, %2)" : "=r"(res64) : "r"(x), "r"(y)); + return res64; +} + +static inline unsigned long long dfmpylh(double acc, double x, double y) +{ + unsigned long long res64 = *(unsigned long long *)&acc; + asm("%0 += dfmpylh(%1, %2)" : "+r"(res64) : "r"(x), "r"(y)); + return res64; +} + +static void check_dfmpyxx(void) +{ + unsigned long long res64; + + res64 = dfmpyll(DBL_MIN, DBL_MIN); + check64(res64, 0ULL); + res64 = dfmpyll(-1.0, DBL_MIN); + check64(res64, 0ULL); + res64 = dfmpyll(DBL_MAX, DBL_MAX); + check64(res64, 0x1fffffffdULL); + + res64 = dfmpylh(DBL_MIN, DBL_MIN, DBL_MIN); + check64(res64, 0x10000000000000ULL); + res64 = dfmpylh(-1.0, DBL_MAX, DBL_MIN); + check64(res64, 0xc00fffffffe00000ULL); + res64 = dfmpylh(DBL_MAX, 0.0, -1.0); + check64(res64, 0x7fefffffffffffffULL); +} + int main() { check_compare_exception(); @@ -718,6 +770,8 @@ int main() check_sffixupd(); check_sffms(); check_float2int_convs(); + check_float_consts(); + check_dfmpyxx(); puts(err ? "FAIL" : "PASS"); return err ? 1 : 0; diff --git a/tests/tcg/hexagon/misc.c b/tests/tcg/hexagon/misc.c index 4fcbb22..cfdda3f 100644 --- a/tests/tcg/hexagon/misc.c +++ b/tests/tcg/hexagon/misc.c @@ -391,6 +391,39 @@ void test_count_trailing_zeros_ones(void) check(ct1p(0xffffff0fffffffffULL), 36); } +static inline int dpmpyss_rnd_s0(int x, int y) +{ + int res; + asm("%0 = mpy(%1, %2):rnd\n\t" : "=r"(res) : "r"(x), "r"(y)); + return res; +} + +void test_dpmpyss_rnd_s0(void) +{ + check(dpmpyss_rnd_s0(-1, 0x80000000), 1); + check(dpmpyss_rnd_s0(0, 0x80000000), 0); + check(dpmpyss_rnd_s0(1, 0x80000000), 0); + check(dpmpyss_rnd_s0(0x7fffffff, 0x80000000), 0xc0000001); + check(dpmpyss_rnd_s0(0x80000000, -1), 1); + check(dpmpyss_rnd_s0(-1, -1), 0); + check(dpmpyss_rnd_s0(0, -1), 0); + check(dpmpyss_rnd_s0(1, -1), 0); + check(dpmpyss_rnd_s0(0x7fffffff, -1), 0); + check(dpmpyss_rnd_s0(0x80000000, 0), 0); + check(dpmpyss_rnd_s0(-1, 0), 0); + check(dpmpyss_rnd_s0(0, 0), 0); + check(dpmpyss_rnd_s0(1, 0), 0); + check(dpmpyss_rnd_s0(-1, -1), 0); + check(dpmpyss_rnd_s0(0, -1), 0); + check(dpmpyss_rnd_s0(1, -1), 0); + check(dpmpyss_rnd_s0(0x7fffffff, 1), 0); + check(dpmpyss_rnd_s0(0x80000000, 0x7fffffff), 0xc0000001); + check(dpmpyss_rnd_s0(-1, 0x7fffffff), 0); + check(dpmpyss_rnd_s0(0, 0x7fffffff), 0); + check(dpmpyss_rnd_s0(1, 0x7fffffff), 0); + check(dpmpyss_rnd_s0(0x7fffffff, 0x7fffffff), 0x3fffffff); +} + int main() { int res; @@ -534,6 +567,8 @@ int main() test_count_trailing_zeros_ones(); + test_dpmpyss_rnd_s0(); + puts(err ? "FAIL" : "PASS"); return err; } -- cgit v1.1 From 14edcf11e297252c995d5909144f3751b7383efc Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Mon, 8 May 2023 10:37:23 -0300 Subject: Hexagon (decode): look for pkts with multiple insns at the same slot Each slot in a packet can be assigned to at most one instruction. Although the assembler generally ought to enforce this rule, we better be safe than sorry and also do some check to properly throw an "invalid packet" exception on wrong slot assignments. This should also make it easier to debug possible future errors caused by missing updates to `find_iclass_slots()` rules in target/hexagon/iclass.c. Co-authored-by: Taylor Simpson Signed-off-by: Taylor Simpson Signed-off-by: Matheus Tavares Bernardino Reviewed-by: Taylor Simpson Tested-by: Taylor Simpson Message-Id: --- tests/tcg/hexagon/Makefile.target | 7 +++++++ tests/tcg/hexagon/invalid-slots.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/tcg/hexagon/invalid-slots.c (limited to 'tests') diff --git a/tests/tcg/hexagon/Makefile.target b/tests/tcg/hexagon/Makefile.target index 6109a7e..890ccee 100644 --- a/tests/tcg/hexagon/Makefile.target +++ b/tests/tcg/hexagon/Makefile.target @@ -50,6 +50,13 @@ HEX_TESTS += vector_add_int HEX_TESTS += scatter_gather HEX_TESTS += hvx_misc HEX_TESTS += hvx_histogram +HEX_TESTS += invalid-slots + +run-and-check-exception = $(call run-test,$2,$3 2>$2.stderr; \ + test $$? -eq 1 && grep -q "exception $(strip $1)" $2.stderr) + +run-invalid-slots: invalid-slots + $(call run-and-check-exception, 0x15, $@, $(QEMU) $(QEMU_OPTS) $<) HEX_TESTS += test_abs HEX_TESTS += test_bitcnt diff --git a/tests/tcg/hexagon/invalid-slots.c b/tests/tcg/hexagon/invalid-slots.c new file mode 100644 index 0000000..366ce4f --- /dev/null +++ b/tests/tcg/hexagon/invalid-slots.c @@ -0,0 +1,29 @@ +/* + * Copyright(c) 2023 Qualcomm Innovation Center, Inc. All Rights Reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +char mem[8] __attribute__((aligned(8))); + +int main() +{ + asm volatile( + "r0 = #mem\n" + /* Invalid packet (2 instructions at slot 0): */ + ".word 0xa1804100\n" /* { memw(r0) = r1; */ + ".word 0x28032804\n" /* r3 = #0; r4 = #0 } */ + : : : "r0", "r3", "r4", "memory"); + return 0; +} -- cgit v1.1 From 9e6d4938d106ca775108ec2a1fecc6d789543088 Mon Sep 17 00:00:00 2001 From: Marco Liebel Date: Tue, 9 May 2023 11:42:31 -0700 Subject: Remove test_vshuff from hvx_misc tests test_vshuff checks that the vshuff instruction works correctly when both vector registers are the same. Using vshuff in this way is undefined and will be rejected by the compiler in a future version of the toolchain. Signed-off-by: Marco Liebel Reviewed-by: Brian Cain Reviewed-by: Taylor Simpson Tested-by: Taylor Simpson Signed-off-by: Taylor Simpson Message-Id: <20230509184231.2467626-1-quic_mliebel@quicinc.com> --- tests/tcg/hexagon/hvx_misc.c | 45 -------------------------------------------- 1 file changed, 45 deletions(-) (limited to 'tests') diff --git a/tests/tcg/hexagon/hvx_misc.c b/tests/tcg/hexagon/hvx_misc.c index c89fe02..09dec8d 100644 --- a/tests/tcg/hexagon/hvx_misc.c +++ b/tests/tcg/hexagon/hvx_misc.c @@ -342,49 +342,6 @@ static void test_vsubuwsat_dv(void) check_output_w(__LINE__, 2); } -static void test_vshuff(void) -{ - /* Test that vshuff works when the two operands are the same register */ - const uint32_t splat = 0x089be55c; - const uint32_t shuff = 0x454fa926; - MMVector v0, v1; - - memset(expect, 0x12, sizeof(MMVector)); - memset(output, 0x34, sizeof(MMVector)); - - asm volatile("v25 = vsplat(%0)\n\t" - "vshuff(v25, v25, %1)\n\t" - "vmem(%2 + #0) = v25\n\t" - : /* no outputs */ - : "r"(splat), "r"(shuff), "r"(output) - : "v25", "memory"); - - /* - * The semantics of Hexagon are the operands are pass-by-value, so create - * two copies of the vsplat result. - */ - for (int i = 0; i < MAX_VEC_SIZE_BYTES / 4; i++) { - v0.uw[i] = splat; - v1.uw[i] = splat; - } - /* Do the vshuff operation */ - for (int offset = 1; offset < MAX_VEC_SIZE_BYTES; offset <<= 1) { - if (shuff & offset) { - for (int k = 0; k < MAX_VEC_SIZE_BYTES; k++) { - if (!(k & offset)) { - uint8_t tmp = v0.ub[k]; - v0.ub[k] = v1.ub[k + offset]; - v1.ub[k + offset] = tmp; - } - } - } - } - /* Put the result in the expect buffer for verification */ - expect[0] = v1; - - check_output_b(__LINE__, 1); -} - static void test_load_tmp_predicated(void) { void *p0 = buffer0; @@ -508,8 +465,6 @@ int main() test_vadduwsat(); test_vsubuwsat_dv(); - test_vshuff(); - test_load_tmp_predicated(); test_load_cur_predicated(); -- cgit v1.1 From dae66a3f669eaf0e33447ed42a36ad4ee2f178f2 Mon Sep 17 00:00:00 2001 From: Matheus Tavares Bernardino Date: Thu, 4 May 2023 12:37:32 -0300 Subject: gdbstub: add test for untimely stop-reply packets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the previous commit, we modified gdbstub.c to only send stop-reply packets as a response to GDB commands that accept it. Now, let's add a test for this intended behavior. Running this test before the fix from the previous commit fails as QEMU sends a stop-reply packet asynchronously, when GDB was in fact waiting an ACK. Signed-off-by: Matheus Tavares Bernardino Acked-by: Alex Bennée Signed-off-by: Taylor Simpson Message-Id: --- tests/guest-debug/run-test.py | 16 ++++++++++++---- tests/tcg/multiarch/system/Makefile.softmmu-target | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) (limited to 'tests') diff --git a/tests/guest-debug/run-test.py b/tests/guest-debug/run-test.py index d865e46..de6106a 100755 --- a/tests/guest-debug/run-test.py +++ b/tests/guest-debug/run-test.py @@ -26,11 +26,12 @@ def get_args(): parser.add_argument("--qargs", help="Qemu arguments for test") parser.add_argument("--binary", help="Binary to debug", required=True) - parser.add_argument("--test", help="GDB test script", - required=True) + parser.add_argument("--test", help="GDB test script") parser.add_argument("--gdb", help="The gdb binary to use", default=None) + parser.add_argument("--gdb-args", help="Additional gdb arguments") parser.add_argument("--output", help="A file to redirect output to") + parser.add_argument("--stderr", help="A file to redirect stderr to") return parser.parse_args() @@ -58,6 +59,10 @@ if __name__ == '__main__': output = open(args.output, "w") else: output = None + if args.stderr: + stderr = open(args.stderr, "w") + else: + stderr = None socket_dir = TemporaryDirectory("qemu-gdbstub") socket_name = os.path.join(socket_dir.name, "gdbstub.socket") @@ -77,6 +82,8 @@ if __name__ == '__main__': # Now launch gdb with our test and collect the result gdb_cmd = "%s %s" % (args.gdb, args.binary) + if args.gdb_args: + gdb_cmd += " %s" % (args.gdb_args) # run quietly and ignore .gdbinit gdb_cmd += " -q -n -batch" # disable prompts in case of crash @@ -84,13 +91,14 @@ if __name__ == '__main__': # connect to remote gdb_cmd += " -ex 'target remote %s'" % (socket_name) # finally the test script itself - gdb_cmd += " -x %s" % (args.test) + if args.test: + gdb_cmd += " -x %s" % (args.test) sleep(1) log(output, "GDB CMD: %s" % (gdb_cmd)) - result = subprocess.call(gdb_cmd, shell=True, stdout=output) + result = subprocess.call(gdb_cmd, shell=True, stdout=output, stderr=stderr) # A result of greater than 128 indicates a fatal signal (likely a # crash due to gdb internal failure). That's a problem for GDB and diff --git a/tests/tcg/multiarch/system/Makefile.softmmu-target b/tests/tcg/multiarch/system/Makefile.softmmu-target index 5f432c9..fe40195 100644 --- a/tests/tcg/multiarch/system/Makefile.softmmu-target +++ b/tests/tcg/multiarch/system/Makefile.softmmu-target @@ -27,6 +27,20 @@ run-gdbstub-memory: memory "-monitor none -display none -chardev file$(COMMA)path=$<.out$(COMMA)id=output $(QEMU_OPTS)" \ --bin $< --test $(MULTIARCH_SRC)/gdbstub/memory.py, \ softmmu gdbstub support) + +run-gdbstub-untimely-packet: hello + $(call run-test, $@, $(GDB_SCRIPT) \ + --gdb $(HAVE_GDB_BIN) \ + --gdb-args "-ex 'set debug remote 1'" \ + --output untimely-packet.gdb.out \ + --stderr untimely-packet.gdb.err \ + --qemu $(QEMU) \ + --bin $< --qargs \ + "-monitor none -display none -chardev file$(COMMA)path=untimely-packet.out$(COMMA)id=output $(QEMU_OPTS)", \ + "softmmu gdbstub untimely packets") + $(call quiet-command, \ + (! grep -Fq 'Packet instead of Ack, ignoring it' untimely-packet.gdb.err), \ + "GREP", "file untimely-packet.gdb.err") else run-gdbstub-%: $(call skip-test, "gdbstub test $*", "no guest arch support") @@ -36,4 +50,4 @@ run-gdbstub-%: $(call skip-test, "gdbstub test $*", "need working gdb") endif -MULTIARCH_RUNS += run-gdbstub-memory +MULTIARCH_RUNS += run-gdbstub-memory run-gdbstub-untimely-packet -- cgit v1.1