1 /* { dg-do run } */
2 /* { dg-require-effective-target p9vector_hw } */
3 /* { dg-options "-O2 -mdejagnu-cpu=power9 -save-temps" } */
4 
5 /* Verify the vec_rlm and vec_rlmi builtins works correctly.  */
6 /* { dg-final { scan-assembler-times {\mvrldmi\M} 1 } } */
7 
8 #include <altivec.h>
9 
10 #ifdef DEBUG
11 #include <stdio.h>
12 #include <stdlib.h>
13 #endif
14 
15 void abort (void);
16 
main()17 int main ()
18 {
19   int i;
20 
21   vector unsigned int vec_arg1_int, vec_arg2_int, vec_arg3_int;
22   vector unsigned int vec_result_int, vec_expected_result_int;
23 
24   vector unsigned long long int vec_arg1_di, vec_arg2_di, vec_arg3_di;
25   vector unsigned long long int vec_result_di, vec_expected_result_di;
26 
27   unsigned int mask_begin, mask_end, shift;
28   unsigned long long int mask;
29 
30 /* Check vec int version of vec_rlmi builtin */
31   mask = 0;
32   mask_begin = 0;
33   mask_end   = 4;
34   shift = 16;
35 
36   for (i = 0; i < 31; i++)
37     if ((i >= mask_begin) && (i <= mask_end))
38       mask |= 0x80000000ULL >> i;
39 
40   for (i = 0; i < 4; i++) {
41     vec_arg1_int[i] = 0x12345678 + i*0x11111111;
42     vec_arg2_int[i] = 0xA1B1CDEF;
43     vec_arg3_int[i] = mask_begin << 16 | mask_end << 8 | shift;
44 
45     /* do rotate */
46     vec_expected_result_int[i] =  ( vec_arg2_int[i] & ~mask)
47       | ((vec_arg1_int[i] << shift) | (vec_arg1_int[i] >> (32-shift))) & mask;
48 
49   }
50 
51   /* vec_rlmi(arg1, arg2, arg3)
52      result - rotate each element of arg2 left and inserts it into arg1
53      element based on the mask specified in arg3.  The shift, mask
54      start and end is specified in arg3.  */
55   vec_result_int = vec_rlmi (vec_arg1_int, vec_arg2_int, vec_arg3_int);
56 
57   for (i = 0; i < 4; i++) {
58     if (vec_result_int[i] != vec_expected_result_int[i])
59 #ifdef DEBUG
60       printf("ERROR: i = %d, vec_rlmi int result 0x%x, does not match "
61 	     "expected result 0x%x\n", i, vec_result_int[i],
62 	     vec_expected_result_int[i]);
63 #else
64       abort();
65 #endif
66     }
67 
68 /* Check vec long long int version of vec_rlmi builtin */
69   mask = 0;
70   mask_begin = 0;
71   mask_end   = 4;
72   shift = 16;
73 
74   for (i = 0; i < 31; i++)
75     if ((i >= mask_begin) && (i <= mask_end))
76       mask |= 0x8000000000000000ULL >> i;
77 
78   for (i = 0; i < 2; i++) {
79     vec_arg1_di[i] = 0x1234567800000000 + i*0x11111111;
80     vec_arg2_di[i] = 0xA1B1C1D1E1F12345;
81     vec_arg3_di[i] = mask_begin << 16 | mask_end << 8 | shift;
82 
83     /* do rotate */
84     vec_expected_result_di[i] =  ( vec_arg2_di[i] & ~mask)
85       | ((vec_arg1_di[i] << shift) | (vec_arg1_di[i] >> (64-shift))) & mask;
86   }
87 
88   /* vec_rlmi(arg1, arg2, arg3)
89      result - rotate each element of arg1 left and inserts it into arg2
90      element based on the mask specified in arg3.  The shift, mask, start
91      and end is specified in arg3.  */
92   vec_result_di = vec_rlmi (vec_arg1_di, vec_arg2_di, vec_arg3_di);
93 
94   for (i = 0; i < 2; i++) {
95     if (vec_result_di[i] != vec_expected_result_di[i])
96 #ifdef DEBUG
97       printf("ERROR: i = %d, vec_rlmi int long long result 0x%llx, does not match "
98 	     "expected result 0x%llx\n", i, vec_result_di[i],
99 	     vec_expected_result_di[i]);
100 #else
101       abort();
102 #endif
103     }
104 
105   /* Check vec int version of vec_rlnm builtin */
106   mask = 0;
107   mask_begin = 0;
108   mask_end   = 4;
109   shift = 16;
110 
111   for (i = 0; i < 31; i++)
112     if ((i >= mask_begin) && (i <= mask_end))
113       mask |= 0x80000000ULL >> i;
114 
115   for (i = 0; i < 4; i++) {
116     vec_arg1_int[i] = 0x12345678 + i*0x11111111;
117     vec_arg2_int[i] = shift;
118     vec_arg3_int[i] = mask_begin << 8 | mask_end;
119     vec_expected_result_int[i] = (vec_arg1_int[i] << shift) & mask;
120   }
121 
122   /* vec_rlnm(arg1, arg2, arg3)
123      result - rotate each element of arg1 left by shift in element of arg2.
124        Then AND with mask whose  start/stop bits are specified in element of
125        arg3.  */
126   vec_result_int = vec_rlnm (vec_arg1_int, vec_arg2_int, vec_arg3_int);
127   for (i = 0; i < 4; i++) {
128     if (vec_result_int[i] != vec_expected_result_int[i])
129 #ifdef DEBUG
130       printf("ERROR: vec_rlnm, i = %d, int result 0x%x does not match "
131 	     "expected result 0x%x\n", i, vec_result_int[i],
132 	     vec_expected_result_int[i]);
133 #else
134       abort();
135 #endif
136     }
137 
138 /* Check vec long int version of builtin */
139   mask = 0;
140   mask_begin = 0;
141   mask_end   = 4;
142   shift = 20;
143 
144   for (i = 0; i < 63; i++)
145     if ((i >= mask_begin) && (i <= mask_end))
146       mask |= 0x8000000000000000ULL >> i;
147 
148   for (i = 0; i < 2; i++) {
149     vec_arg1_di[i] = 0x123456789ABCDE00ULL + i*0x1111111111111111ULL;
150     vec_arg2_di[i] = shift;
151     vec_arg3_di[i] = mask_begin << 8 | mask_end;
152     vec_expected_result_di[i] = (vec_arg1_di[i] << shift) & mask;
153   }
154 
155   vec_result_di = vec_rlnm (vec_arg1_di, vec_arg2_di, vec_arg3_di);
156 
157   for (i = 0; i < 2; i++) {
158     if (vec_result_di[i] != vec_expected_result_di[i])
159 #ifdef DEBUG
160       printf("ERROR: vec_rlnm, i = %d, long long int result 0x%llx does not "
161 	     "match expected result 0x%llx\n", i, vec_result_di[i],
162 	     vec_expected_result_di[i]);
163 #else
164       abort();
165 #endif
166     }
167 
168     /* Check vec int version of vec_vrlnm builtin */
169   mask = 0;
170   mask_begin = 0;
171   mask_end   = 4;
172   shift = 16;
173 
174   for (i = 0; i < 31; i++)
175     if ((i >= mask_begin) && (i <= mask_end))
176       mask |= 0x80000000ULL >> i;
177 
178   for (i = 0; i < 4; i++) {
179     vec_arg1_int[i] = 0x12345678 + i*0x11111111;
180     vec_arg2_int[i] = mask_begin << 16 | mask_end << 8 | shift;
181     vec_expected_result_int[i] = (vec_arg1_int[i] << shift) & mask;
182   }
183 
184   /* vec_vrlnm(arg1, arg2, arg3)
185      result - rotate each element of arg1 left then AND with mask.  The mask
186        start, stop bits is specified in the second argument.  The shift amount
187        is also specified in the second argument.  */
188   vec_result_int = vec_vrlnm (vec_arg1_int, vec_arg2_int);
189 
190   for (i = 0; i < 4; i++) {
191     if (vec_result_int[i] != vec_expected_result_int[i])
192 #ifdef DEBUG
193       printf("ERROR: vec_vrlnm, i = %d, int result 0x%x does not match "
194 	     "expected result 0x%x\n", i, vec_result_int[i],
195 	     vec_expected_result_int[i]);
196 #else
197       abort();
198 #endif
199     }
200 
201 /* Check vec long int version of vec_vrlnm builtin */
202   mask = 0;
203   mask_begin = 0;
204   mask_end   = 4;
205   shift = 20;
206 
207   for (i = 0; i < 63; i++)
208     if ((i >= mask_begin) && (i <= mask_end))
209       mask |= 0x8000000000000000ULL >> i;
210 
211   for (i = 0; i < 2; i++) {
212     vec_arg1_di[i] = 0x123456789ABCDE00ULL + i*0x1111111111111111ULL;
213     vec_arg2_di[i] = mask_begin << 16 | mask_end << 8 | shift;
214     vec_expected_result_di[i] = (vec_arg1_di[i] << shift) & mask;
215   }
216 
217   vec_result_di = vec_vrlnm (vec_arg1_di, vec_arg2_di);
218 
219   for (i = 0; i < 2; i++) {
220     if (vec_result_di[i] != vec_expected_result_di[i])
221 #ifdef DEBUG
222       printf("ERROR: vec_vrlnm, i = %d, long long int result 0x%llx does not "
223 	     "match expected result 0x%llx\n", i, vec_result_di[i],
224 	     vec_expected_result_di[i]);
225 #else
226       abort();
227 #endif
228     }
229 
230   return 0;
231 }
232