1This directory contains executable tests for ARM/AArch64 Advanced SIMD 2(Neon) intrinsics. 3 4It is meant to cover execution cases of all the Advanced SIMD 5intrinsics, but does not scan the generated assembler code. 6 7The general framework is composed as follows: 8- advsimd-intrinsics.exp: main dejagnu driver 9- *.c: actual tests, generally one per intrinsinc family 10- arm-neon-ref.h: contains macro definitions to save typing in actual 11 test files 12- compute-ref-data.h: contains input vectors definitions 13- *.inc: generic tests, shared by several families of intrinsics. For 14 instance, unary or binary operators 15 16A typical .c test file starts with the following contents (look at 17vld1.c and vaba.c for sample cases): 18#include <arm_neon.h> 19#include "arm-neon-ref.h" 20#include "compute-ref-data.h" 21 22Then, definitions of expected results, based on common input values, 23as defined in compute-ref-data.h. 24For example: 25VECT_VAR_DECL(expected,int,16,4) [] = { 0x16, 0x17, 0x18, 0x19 }; 26defines the expected results of an operator generating int16x4 values. 27 28The common input values defined in compute-ref-data.h have been chosen 29to avoid corner-case values for most operators, yet exposing negative 30values for signed operators. For this reason, their range is also 31limited. For instance, the initialization of buffer_int16x4 will be 32{ -16, -15, -14, -13 }. 33 34The initialization of floating-point values is done via hex notation, 35to avoid potential rounding problems. 36 37To test special values and corner cases, specific initialization 38values should be used in dedicated tests, to ensure proper coverage. 39An example of this is vshl. 40 41When a variant of an intrinsic is not available, its expected result 42should be defined to the value of CLEAN_PATTERN_8 as defined in 43arm-neon-ref.h. For example: 44VECT_VAR_DECL(expected,int,64,1) [] = { 0x3333333333333333 }; 45if the given intrinsic has no variant producing an int64x1 result, 46like the vcmp family (eg. vclt). 47 48This is because the helper function (check_results(), defined in 49arm-neon-ref.h), iterates over all the possible variants, to save 50typing in each individual test file. Alternatively, one can directly 51call the CHECK/CHECK_FP macros to check only a few expected results 52(see vabs.c for an example). 53 54Then, define the TEST_MSG string, which will be used when reporting errors. 55 56Next, define the function performing the actual tests, in general 57relying on the helpers provided by arm-neon-ref.h, which means: 58 59* declare necessary vectors of suitable types: using 60 DECL_VARIABLE_ALL_VARIANTS when all variants are supported, or the 61 relevant of subset calls to DECL_VARIABLE. 62 63* call clean_results() to initialize the 'results' buffers. 64 65* initialize the input vectors, using VLOAD, VDUP or VSET_LANE (vld* 66 tests do not need this step, since their actual purpose is to 67 initialize vectors). 68 69* execute the intrinsic on relevant variants, for instance using 70 TEST_MACRO_ALL_VARIANTS_2_5. 71 72* call check_results() to check that the results match the expected 73 values. 74 75A template test file could be: 76================================================================= 77#include <arm_neon.h> 78#include "arm-neon-ref.h" 79#include "compute-ref-data.h" 80 81/* Expected results. */ 82VECT_VAR_DECL(expected,int,8,8) [] = { 0xf6, 0xf7, 0xf8, 0xf9, 83 0xfa, 0xfb, 0xfc, 0xfd }; 84/* and as many others as necessary. */ 85 86#define TEST_MSG "VMYINTRINSIC" 87void exec_myintrinsic (void) 88{ 89 /* my test: v4=vmyintrinsic(v1,v2,v3), then store the result. */ 90#define TEST_VMYINTR(Q, T1, T2, W, N) \ 91 VECT_VAR(vector_res, T1, W, N) = \ 92 vmyintr##Q##_##T2##W(VECT_VAR(vector1, T1, W, N), \ 93 VECT_VAR(vector2, T1, W, N), \ 94 VECT_VAR(vector3, T1, W, N)); \ 95 vst1##Q##_##T2##W(VECT_VAR(result, T1, W, N), VECT_VAR(vector_res, T1, W, N)) 96 97#define DECL_VMYINTR_VAR(VAR) \ 98 DECL_VARIABLE(VAR, int, 8, 8); 99/* And as many others as necessary. */ 100 101 DECL_VMYINTR_VAR(vector1); 102 DECL_VMYINTR_VAR(vector2); 103 DECL_VMYINTR_VAR(vector3); 104 DECL_VMYINTR_VAR(vector_res); 105 106 clean_results (); 107 108 /* Initialize input "vector1" from "buffer". */ 109 VLOAD(vector1, buffer, , int, s, 8, 8); 110/* And as many others as necessary. */ 111 112 /* Choose init value arbitrarily. */ 113 VDUP(vector2, , int, s, 8, 8, 1); 114/* And as many others as necessary. */ 115 116 /* Choose init value arbitrarily. */ 117 VDUP(vector3, , int, s, 8, 8, -5); 118/* And as many others as necessary. */ 119 120 /* Execute the tests. */ 121 TEST_VMYINTR(, int, s, 8, 8); 122/* And as many others as necessary. */ 123 124 check_results (TEST_MSG, ""); 125} 126 127int main (void) 128{ 129 exec_vmyintrinsic (); 130 return 0; 131} 132================================================================= 133