1 #include <arm_neon.h>
2 #include "arm-neon-ref.h"
3 #include "compute-ref-data.h"
4 
5 /* Expected values of cumulative_saturation flag.  */
6 int VECT_VAR(expected_cumulative_sat,int,16,4) = 0;
7 int VECT_VAR(expected_cumulative_sat,int,32,2) = 0;
8 int VECT_VAR(expected_cumulative_sat,int,16,8) = 0;
9 int VECT_VAR(expected_cumulative_sat,int,32,4) = 0;
10 
11 /* Expected results.  */
12 VECT_VAR_DECL(expected,int,16,4) [] = { 0xfff5, 0xfff6, 0xfff7, 0xfff7 };
13 VECT_VAR_DECL(expected,int,32,2) [] = { 0x0, 0x0 };
14 VECT_VAR_DECL(expected,int,16,8) [] = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };
15 VECT_VAR_DECL(expected,int,32,4) [] = { 0x0, 0x0, 0x0, 0x0 };
16 
17 /* Expected values of cumulative_saturation flag when multiplication
18    saturates.  */
19 int VECT_VAR(expected_cumulative_sat_mul,int,16,4) = 1;
20 int VECT_VAR(expected_cumulative_sat_mul,int,32,2) = 1;
21 int VECT_VAR(expected_cumulative_sat_mul,int,16,8) = 1;
22 int VECT_VAR(expected_cumulative_sat_mul,int,32,4) = 1;
23 
24 /* Expected results when multiplication saturates.  */
25 VECT_VAR_DECL(expected_mul,int,16,4) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
26 VECT_VAR_DECL(expected_mul,int,32,2) [] = { 0x7fffffff, 0x7fffffff };
27 VECT_VAR_DECL(expected_mul,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
28 					    0x7fff, 0x7fff, 0x7fff, 0x7fff };
29 VECT_VAR_DECL(expected_mul,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
30 					    0x7fffffff, 0x7fffffff };
31 
32 /* Expected values of cumulative_saturation flag when rounding
33    should not cause saturation.  */
34 int VECT_VAR(expected_cumulative_sat_round,int,16,4) = 0;
35 int VECT_VAR(expected_cumulative_sat_round,int,32,2) = 0;
36 int VECT_VAR(expected_cumulative_sat_round,int,16,8) = 0;
37 int VECT_VAR(expected_cumulative_sat_round,int,32,4) = 0;
38 
39 /* Expected results when rounding should not cause saturation.  */
40 VECT_VAR_DECL(expected_round,int,16,4) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff };
41 VECT_VAR_DECL(expected_round,int,32,2) [] = { 0x7fffffff, 0x7fffffff };
42 VECT_VAR_DECL(expected_round,int,16,8) [] = { 0x7fff, 0x7fff, 0x7fff, 0x7fff,
43 					      0x7fff, 0x7fff, 0x7fff, 0x7fff };
44 VECT_VAR_DECL(expected_round,int,32,4) [] = { 0x7fffffff, 0x7fffffff,
45 					      0x7fffffff, 0x7fffffff };
46 
47 #define INSN vqrdmulh
48 #define TEST_MSG "VQRDMULH"
49 
50 #define FNNAME1(NAME) void exec_ ## NAME (void)
51 #define FNNAME(NAME) FNNAME1(NAME)
52 
FNNAME(INSN)53 FNNAME (INSN)
54 {
55   /* vector_res = vqrdmulh(vector,vector2), then store the result.  */
56 #define TEST_VQRDMULH2(INSN, Q, T1, T2, W, N, EXPECTED_CUMULATIVE_SAT, CMT) \
57   Set_Neon_Cumulative_Sat(0, VECT_VAR(vector_res, T1, W, N));		\
58   VECT_VAR(vector_res, T1, W, N) =					\
59     INSN##Q##_##T2##W(VECT_VAR(vector, T1, W, N),			\
60 		      VECT_VAR(vector2, T1, W, N));			\
61   vst1##Q##_##T2##W(VECT_VAR(result, T1, W, N),				\
62 		    VECT_VAR(vector_res, T1, W, N));			\
63   CHECK_CUMULATIVE_SAT(TEST_MSG, T1, W, N, EXPECTED_CUMULATIVE_SAT, CMT)
64 
65   /* Two auxliary macros are necessary to expand INSN */
66 #define TEST_VQRDMULH1(INSN, Q, T1, T2, W, N, EXPECTED_CUMULATIVE_SAT, CMT) \
67   TEST_VQRDMULH2(INSN, Q, T1, T2, W, N, EXPECTED_CUMULATIVE_SAT, CMT)
68 
69 #define TEST_VQRDMULH(Q, T1, T2, W, N, EXPECTED_CUMULATIVE_SAT, CMT)	\
70   TEST_VQRDMULH1(INSN, Q, T1, T2, W, N, EXPECTED_CUMULATIVE_SAT, CMT)
71 
72 
73   DECL_VARIABLE(vector, int, 16, 4);
74   DECL_VARIABLE(vector, int, 32, 2);
75   DECL_VARIABLE(vector, int, 16, 8);
76   DECL_VARIABLE(vector, int, 32, 4);
77 
78   DECL_VARIABLE(vector_res, int, 16, 4);
79   DECL_VARIABLE(vector_res, int, 32, 2);
80   DECL_VARIABLE(vector_res, int, 16, 8);
81   DECL_VARIABLE(vector_res, int, 32, 4);
82 
83   DECL_VARIABLE(vector2, int, 16, 4);
84   DECL_VARIABLE(vector2, int, 32, 2);
85   DECL_VARIABLE(vector2, int, 16, 8);
86   DECL_VARIABLE(vector2, int, 32, 4);
87 
88   clean_results ();
89 
90   VLOAD(vector, buffer, , int, s, 16, 4);
91   VLOAD(vector, buffer, , int, s, 32, 2);
92   VLOAD(vector, buffer, q, int, s, 16, 8);
93   VLOAD(vector, buffer, q, int, s, 32, 4);
94 
95   /* Initialize vector2.  */
96   VDUP(vector2, , int, s, 16, 4, 0x5555);
97   VDUP(vector2, , int, s, 32, 2, 0xBB);
98   VDUP(vector2, q, int, s, 16, 8, 0x33);
99   VDUP(vector2, q, int, s, 32, 4, 0x22);
100 
101 #define CMT ""
102   TEST_VQRDMULH(, int, s, 16, 4, expected_cumulative_sat, CMT);
103   TEST_VQRDMULH(, int, s, 32, 2, expected_cumulative_sat, CMT);
104   TEST_VQRDMULH(q, int, s, 16, 8, expected_cumulative_sat, CMT);
105   TEST_VQRDMULH(q, int, s, 32, 4, expected_cumulative_sat, CMT);
106 
107   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected, CMT);
108   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected, CMT);
109   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected, CMT);
110   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected, CMT);
111 
112   /* Now use input values such that the multiplication causes
113      saturation.  */
114 #define TEST_MSG_MUL " (check mul cumulative saturation)"
115   VDUP(vector, , int, s, 16, 4, 0x8000);
116   VDUP(vector, , int, s, 32, 2, 0x80000000);
117   VDUP(vector, q, int, s, 16, 8, 0x8000);
118   VDUP(vector, q, int, s, 32, 4, 0x80000000);
119   VDUP(vector2, , int, s, 16, 4, 0x8000);
120   VDUP(vector2, , int, s, 32, 2, 0x80000000);
121   VDUP(vector2, q, int, s, 16, 8, 0x8000);
122   VDUP(vector2, q, int, s, 32, 4, 0x80000000);
123 
124   TEST_VQRDMULH(, int, s, 16, 4, expected_cumulative_sat_mul, TEST_MSG_MUL);
125   TEST_VQRDMULH(, int, s, 32, 2, expected_cumulative_sat_mul, TEST_MSG_MUL);
126   TEST_VQRDMULH(q, int, s, 16, 8, expected_cumulative_sat_mul, TEST_MSG_MUL);
127   TEST_VQRDMULH(q, int, s, 32, 4, expected_cumulative_sat_mul, TEST_MSG_MUL);
128 
129   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected_mul, TEST_MSG_MUL);
130   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected_mul, TEST_MSG_MUL);
131   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_mul, TEST_MSG_MUL);
132   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_mul, TEST_MSG_MUL);
133 
134   /* Use input values where rounding produces a result equal to the
135      saturation value, but does not set the saturation flag.  */
136 #define TEST_MSG_ROUND " (check rounding)"
137   VDUP(vector, , int, s, 16, 4, 0x8000);
138   VDUP(vector, , int, s, 32, 2, 0x80000000);
139   VDUP(vector, q, int, s, 16, 8, 0x8000);
140   VDUP(vector, q, int, s, 32, 4, 0x80000000);
141   VDUP(vector2, , int, s, 16, 4, 0x8001);
142   VDUP(vector2, , int, s, 32, 2, 0x80000001);
143   VDUP(vector2, q, int, s, 16, 8, 0x8001);
144   VDUP(vector2, q, int, s, 32, 4, 0x80000001);
145 
146   TEST_VQRDMULH(, int, s, 16, 4, expected_cumulative_sat_round, TEST_MSG_ROUND);
147   TEST_VQRDMULH(, int, s, 32, 2, expected_cumulative_sat_round, TEST_MSG_ROUND);
148   TEST_VQRDMULH(q, int, s, 16, 8, expected_cumulative_sat_round, TEST_MSG_ROUND);
149   TEST_VQRDMULH(q, int, s, 32, 4, expected_cumulative_sat_round, TEST_MSG_ROUND);
150 
151   CHECK(TEST_MSG, int, 16, 4, PRIx16, expected_round, TEST_MSG_ROUND);
152   CHECK(TEST_MSG, int, 32, 2, PRIx32, expected_round, TEST_MSG_ROUND);
153   CHECK(TEST_MSG, int, 16, 8, PRIx16, expected_round, TEST_MSG_ROUND);
154   CHECK(TEST_MSG, int, 32, 4, PRIx32, expected_round, TEST_MSG_ROUND);
155 }
156 
main(void)157 int main (void)
158 {
159   exec_vqrdmulh ();
160   return 0;
161 }
162