1 #include <arm_neon.h>
2 #include "arm-neon-ref.h"
3 #include "compute-ref-data.h"
4 
5 /* Expected results.  */
6 VECT_VAR_DECL(expected,int,16,4) [] = { 0xfffc, 0xfffc, 0xfffc, 0xfffd };
7 VECT_VAR_DECL(expected,int,32,2) [] = { 0xfffffffe, 0xfffffffe };
8 VECT_VAR_DECL(expected,int,16,8) [] = { 0x6, 0x6, 0x6, 0x5,
9 					0x5, 0x4, 0x4, 0x4 };
10 VECT_VAR_DECL(expected,int,32,4) [] = { 0xfffffffe, 0xfffffffe,
11 					0xfffffffe, 0xfffffffe };
12 
13 /* Expected results when multiplication saturates.  */
14 VECT_VAR_DECL(expected_mul,int,16,4) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
15 VECT_VAR_DECL(expected_mul,int,32,2) [] = { 0x7fffffff, 0x7fffffff };
16 VECT_VAR_DECL(expected_mul,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
17 					    0x7fff, 0x7fff, 0x7fff, 0x7fff };
18 VECT_VAR_DECL(expected_mul,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
19 					    0x7fffffff, 0x7fffffff };
20 
21 /* Expected results when rounding should not cause saturation.  */
22 VECT_VAR_DECL(expected_round,int,16,4) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
23 VECT_VAR_DECL(expected_round,int,32,2) [] = { 0x7fffffff, 0x7fffffff };
24 VECT_VAR_DECL(expected_round,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
25 					      0x7fff, 0x7fff, 0x7fff, 0x7fff };
26 VECT_VAR_DECL(expected_round,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
27 					      0x7fffffff, 0x7fffffff };
28 
29 #define INSN vqrdmulh
30 #define TEST_MSG "VQRDMULH_N"
31 
32 #define FNNAME1(NAME) void exec_ ## NAME ## _n (void)
33 #define FNNAME(NAME) FNNAME1(NAME)
34 
FNNAME(INSN)35 FNNAME (INSN)
36 {
37   int i;
38 
39   /* vector_res = vqrdmulh_n(vector,val), then store the result.  */
40 #define TEST_VQRDMULH_N2(INSN, Q, T1, T2, W, N, L, CMT) \
41   Set_Neon_Cumulative_Sat(0, VECT_VAR(vector_res, T1, W, N));		\
42   VECT_VAR(vector_res, T1, W, N) =					\
43     INSN##Q##_n_##T2##W(VECT_VAR(vector, T1, W, N),			\
44 			L);						\
45   vst1##Q##_##T2##W(VECT_VAR(result, T1, W, N),				\
46 		    VECT_VAR(vector_res, T1, W, N))
47 
48   /* Two auxliary macros are necessary to expand INSN */
49 #define TEST_VQRDMULH_N1(INSN, Q, T1, T2, W, N, L, CMT) \
50   TEST_VQRDMULH_N2(INSN, Q, T1, T2, W, N, L, CMT)
51 
52 #define TEST_VQRDMULH_N(Q, T1, T2, W, N, L, CMT) \
53   TEST_VQRDMULH_N1(INSN, Q, T1, T2, W, N, L, CMT)
54 
55 
56   DECL_VARIABLE(vector, int, 16, 4);
57   DECL_VARIABLE(vector, int, 32, 2);
58   DECL_VARIABLE(vector, int, 16, 8);
59   DECL_VARIABLE(vector, int, 32, 4);
60 
61   DECL_VARIABLE(vector_res, int, 16, 4);
62   DECL_VARIABLE(vector_res, int, 32, 2);
63   DECL_VARIABLE(vector_res, int, 16, 8);
64   DECL_VARIABLE(vector_res, int, 32, 4);
65 
66   clean_results ();
67 
68   VLOAD(vector, buffer, , int, s, 16, 4);
69   VLOAD(vector, buffer, , int, s, 32, 2);
70   VLOAD(vector, buffer, q, int, s, 16, 8);
71   VLOAD(vector, buffer, q, int, s, 32, 4);
72 
73   /* Choose multiplier arbitrarily.  */
74 #define CMT ""
75   TEST_VQRDMULH_N(, int, s, 16, 4, 0x2233, CMT);
76   TEST_VQRDMULH_N(, int, s, 32, 2, 0x12345678, CMT);
77   TEST_VQRDMULH_N(q, int, s, 16, 8, 0xCD12, CMT);
78   TEST_VQRDMULH_N(q, int, s, 32, 4, 0xFA23456, CMT);
79 
80   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected, CMT);
81   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected, CMT);
82   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected, CMT);
83   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected, CMT);
84 
85   /* Now use input values such that the multiplication causes
86      saturation.  */
87 #define TEST_MSG_MUL " (check mul cumulative saturation)"
88   VDUP(vector, , int, s, 16, 4, 0x8000);
89   VDUP(vector, , int, s, 32, 2, 0x80000000);
90   VDUP(vector, q, int, s, 16, 8, 0x8000);
91   VDUP(vector, q, int, s, 32, 4, 0x80000000);
92 
93   TEST_VQRDMULH_N(, int, s, 16, 4, 0x8000, TEST_MSG_MUL);
94   TEST_VQRDMULH_N(, int, s, 32, 2, 0x80000000, TEST_MSG_MUL);
95   TEST_VQRDMULH_N(q, int, s, 16, 8, 0x8000, TEST_MSG_MUL);
96   TEST_VQRDMULH_N(q, int, s, 32, 4, 0x80000000, TEST_MSG_MUL);
97 
98   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected_mul, TEST_MSG_MUL);
99   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected_mul, TEST_MSG_MUL);
100   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_mul, TEST_MSG_MUL);
101   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_mul, TEST_MSG_MUL);
102 
103   /* Use input values where rounding produces a result equal to the
104      saturation value, but does not set the saturation flag.  */
105 #define TEST_MSG_ROUND " (check rounding)"
106   VDUP(vector, , int, s, 16, 4, 0x8000);
107   VDUP(vector, , int, s, 32, 2, 0x80000000);
108   VDUP(vector, q, int, s, 16, 8, 0x8000);
109   VDUP(vector, q, int, s, 32, 4, 0x80000000);
110 
111   TEST_VQRDMULH_N(, int, s, 16, 4, 0x8001, TEST_MSG_ROUND);
112   TEST_VQRDMULH_N(, int, s, 32, 2, 0x80000001, TEST_MSG_ROUND);
113   TEST_VQRDMULH_N(q, int, s, 16, 8, 0x8001, TEST_MSG_ROUND);
114   TEST_VQRDMULH_N(q, int, s, 32, 4, 0x80000001, TEST_MSG_ROUND);
115 
116   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected_round, TEST_MSG_ROUND);
117   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected_round, TEST_MSG_ROUND);
118   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_round, TEST_MSG_ROUND);
119   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_round, TEST_MSG_ROUND);
120 }
121 
main(void)122 int main (void)
123 {
124   exec_vqrdmulh_n ();
125   return 0;
126 }
127