| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| /* | ||
| * 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 <stdint.h> | ||
| #include <stdlib.h> | ||
| #include <stdio.h> | ||
|
|
||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
| #include <stdbool.h> | ||
| #include <string.h> | ||
| #include <limits.h> | ||
|
|
||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| /* | ||
| * 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdint.h> | ||
| #include <stdbool.h> | ||
| #include <string.h> | ||
| #include <limits.h> | ||
|
|
||
| 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; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| { 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, | ||
| }, |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| #include <stdio.h> | ||
| #include <stdbool.h> | ||
| #include <stdint.h> | ||
|
|
||
| /* | ||
| * 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; | ||
| } |