xref: /aosp_15_r20/external/vixl/test/test-api.cc (revision f5c631da2f1efdd72b5fd1e20510e4042af13d77)
1*f5c631daSSadaf Ebrahimi // Copyright 2016, VIXL authors
2*f5c631daSSadaf Ebrahimi // All rights reserved.
3*f5c631daSSadaf Ebrahimi //
4*f5c631daSSadaf Ebrahimi // Redistribution and use in source and binary forms, with or without
5*f5c631daSSadaf Ebrahimi // modification, are permitted provided that the following conditions are met:
6*f5c631daSSadaf Ebrahimi //
7*f5c631daSSadaf Ebrahimi //   * Redistributions of source code must retain the above copyright notice,
8*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer.
9*f5c631daSSadaf Ebrahimi //   * Redistributions in binary form must reproduce the above copyright notice,
10*f5c631daSSadaf Ebrahimi //     this list of conditions and the following disclaimer in the documentation
11*f5c631daSSadaf Ebrahimi //     and/or other materials provided with the distribution.
12*f5c631daSSadaf Ebrahimi //   * Neither the name of ARM Limited nor the names of its contributors may be
13*f5c631daSSadaf Ebrahimi //     used to endorse or promote products derived from this software without
14*f5c631daSSadaf Ebrahimi //     specific prior written permission.
15*f5c631daSSadaf Ebrahimi //
16*f5c631daSSadaf Ebrahimi // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS CONTRIBUTORS "AS IS" AND
17*f5c631daSSadaf Ebrahimi // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18*f5c631daSSadaf Ebrahimi // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19*f5c631daSSadaf Ebrahimi // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
20*f5c631daSSadaf Ebrahimi // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*f5c631daSSadaf Ebrahimi // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22*f5c631daSSadaf Ebrahimi // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23*f5c631daSSadaf Ebrahimi // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24*f5c631daSSadaf Ebrahimi // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25*f5c631daSSadaf Ebrahimi // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26*f5c631daSSadaf Ebrahimi 
27*f5c631daSSadaf Ebrahimi #include <iostream>
28*f5c631daSSadaf Ebrahimi #include <set>
29*f5c631daSSadaf Ebrahimi #include <sstream>
30*f5c631daSSadaf Ebrahimi #include <vector>
31*f5c631daSSadaf Ebrahimi 
32*f5c631daSSadaf Ebrahimi #include "test-runner.h"
33*f5c631daSSadaf Ebrahimi 
34*f5c631daSSadaf Ebrahimi #include "cpu-features.h"
35*f5c631daSSadaf Ebrahimi #include "utils-vixl.h"
36*f5c631daSSadaf Ebrahimi 
37*f5c631daSSadaf Ebrahimi #if __cplusplus >= 201103L
38*f5c631daSSadaf Ebrahimi #include <type_traits>
39*f5c631daSSadaf Ebrahimi #endif
40*f5c631daSSadaf Ebrahimi 
41*f5c631daSSadaf Ebrahimi #define TEST(name) TEST_(API_##name)
42*f5c631daSSadaf Ebrahimi 
43*f5c631daSSadaf Ebrahimi #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
44*f5c631daSSadaf Ebrahimi 
45*f5c631daSSadaf Ebrahimi namespace vixl {
46*f5c631daSSadaf Ebrahimi 
47*f5c631daSSadaf Ebrahimi // Describe the result of a test. Should IsUintN() and IsIntN() return true or
48*f5c631daSSadaf Ebrahimi // false for N and X?
49*f5c631daSSadaf Ebrahimi template <typename T>
50*f5c631daSSadaf Ebrahimi struct UintIntTest {
51*f5c631daSSadaf Ebrahimi   bool is_uintn;
52*f5c631daSSadaf Ebrahimi   bool is_intn;
53*f5c631daSSadaf Ebrahimi   unsigned n;
54*f5c631daSSadaf Ebrahimi   T x;
55*f5c631daSSadaf Ebrahimi };
56*f5c631daSSadaf Ebrahimi 
57*f5c631daSSadaf Ebrahimi // Test IsUintN() and IsIntN() against various values and integral types.
TEST(IsUint_IsInt)58*f5c631daSSadaf Ebrahimi TEST(IsUint_IsInt) {
59*f5c631daSSadaf Ebrahimi   UintIntTest<uint32_t> test_little_values_unsigned[] = {
60*f5c631daSSadaf Ebrahimi       {true, true, 1, UINT32_C(0x0)},   {true, false, 1, UINT32_C(0x1)},
61*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0x2)}, {false, false, 1, UINT32_C(0x3)},
62*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0x4)}, {false, false, 1, UINT32_C(0x5)},
63*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0x6)}, {false, false, 1, UINT32_C(0x7)},
64*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0x8)}, {false, false, 1, UINT32_C(0x9)},
65*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0xa)}, {false, false, 1, UINT32_C(0xb)},
66*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0xc)}, {false, false, 1, UINT32_C(0xd)},
67*f5c631daSSadaf Ebrahimi       {false, false, 1, UINT32_C(0xe)}, {false, false, 1, UINT32_C(0xf)},
68*f5c631daSSadaf Ebrahimi 
69*f5c631daSSadaf Ebrahimi       {true, true, 2, UINT32_C(0x0)},   {true, true, 2, UINT32_C(0x1)},
70*f5c631daSSadaf Ebrahimi       {true, false, 2, UINT32_C(0x2)},  {true, false, 2, UINT32_C(0x3)},
71*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0x4)}, {false, false, 2, UINT32_C(0x5)},
72*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0x6)}, {false, false, 2, UINT32_C(0x7)},
73*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0x8)}, {false, false, 2, UINT32_C(0x9)},
74*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0xa)}, {false, false, 2, UINT32_C(0xb)},
75*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0xc)}, {false, false, 2, UINT32_C(0xd)},
76*f5c631daSSadaf Ebrahimi       {false, false, 2, UINT32_C(0xe)}, {false, false, 2, UINT32_C(0xf)},
77*f5c631daSSadaf Ebrahimi   };
78*f5c631daSSadaf Ebrahimi 
79*f5c631daSSadaf Ebrahimi   UintIntTest<int32_t> test_little_values_signed[] = {
80*f5c631daSSadaf Ebrahimi       {true, true, 1, INT32_C(0)},    {true, false, 1, INT32_C(1)},
81*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(2)},  {false, false, 1, INT32_C(3)},
82*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(4)},  {false, false, 1, INT32_C(5)},
83*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(6)},  {false, false, 1, INT32_C(7)},
84*f5c631daSSadaf Ebrahimi       {false, true, 1, INT32_C(-1)},  {false, false, 1, INT32_C(-2)},
85*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(-3)}, {false, false, 1, INT32_C(-4)},
86*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(-5)}, {false, false, 1, INT32_C(-6)},
87*f5c631daSSadaf Ebrahimi       {false, false, 1, INT32_C(-7)}, {false, false, 1, INT32_C(-8)},
88*f5c631daSSadaf Ebrahimi 
89*f5c631daSSadaf Ebrahimi       {true, true, 2, INT32_C(0)},    {true, true, 2, INT32_C(1)},
90*f5c631daSSadaf Ebrahimi       {true, false, 2, INT32_C(2)},   {true, false, 2, INT32_C(3)},
91*f5c631daSSadaf Ebrahimi       {false, false, 2, INT32_C(4)},  {false, false, 2, INT32_C(5)},
92*f5c631daSSadaf Ebrahimi       {false, false, 2, INT32_C(6)},  {false, false, 2, INT32_C(7)},
93*f5c631daSSadaf Ebrahimi       {false, true, 2, INT32_C(-1)},  {false, true, 2, INT32_C(-2)},
94*f5c631daSSadaf Ebrahimi       {false, false, 2, INT32_C(-3)}, {false, false, 2, INT32_C(-4)},
95*f5c631daSSadaf Ebrahimi       {false, false, 2, INT32_C(-5)}, {false, false, 2, INT32_C(-6)},
96*f5c631daSSadaf Ebrahimi       {false, false, 2, INT32_C(-7)}, {false, false, 2, INT32_C(-8)},
97*f5c631daSSadaf Ebrahimi   };
98*f5c631daSSadaf Ebrahimi 
99*f5c631daSSadaf Ebrahimi   UintIntTest<uint32_t> test_u16[] = {
100*f5c631daSSadaf Ebrahimi       {true, true, 16, UINT32_C(0x0)},
101*f5c631daSSadaf Ebrahimi       {true, false, 16, UINT32_C(0xabcd)},
102*f5c631daSSadaf Ebrahimi       {true, false, 16, UINT32_C(0x8000)},
103*f5c631daSSadaf Ebrahimi       {true, false, 16, UINT32_C(0xffff)},
104*f5c631daSSadaf Ebrahimi       {false, false, 16, UINT32_C(0x10000)},
105*f5c631daSSadaf Ebrahimi       {false, false, 16, UINT32_C(0xffff0000)},
106*f5c631daSSadaf Ebrahimi       {false, false, 16, UINT32_C(0xffff8000)},
107*f5c631daSSadaf Ebrahimi       {false, false, 16, UINT32_C(0xffffffff)},
108*f5c631daSSadaf Ebrahimi   };
109*f5c631daSSadaf Ebrahimi 
110*f5c631daSSadaf Ebrahimi   UintIntTest<int32_t> test_i16[] = {
111*f5c631daSSadaf Ebrahimi       {true, true, 16, INT32_C(0x0)},
112*f5c631daSSadaf Ebrahimi       {true, false, 16, INT32_C(0xabcd)},
113*f5c631daSSadaf Ebrahimi       {true, false, 16, INT32_C(0x8000)},
114*f5c631daSSadaf Ebrahimi       {true, false, 16, INT32_C(0xffff)},
115*f5c631daSSadaf Ebrahimi       {false, false, 16, INT32_C(0x10000)},
116*f5c631daSSadaf Ebrahimi       {true, true, 16, INT32_C(42)},
117*f5c631daSSadaf Ebrahimi       {false, true, 16, INT32_C(-42)},
118*f5c631daSSadaf Ebrahimi       {false, true, 16, INT32_C(-1)},
119*f5c631daSSadaf Ebrahimi   };
120*f5c631daSSadaf Ebrahimi 
121*f5c631daSSadaf Ebrahimi   UintIntTest<uint64_t> test_u32[] = {
122*f5c631daSSadaf Ebrahimi       {true, true, 32, UINT64_C(0x0)},
123*f5c631daSSadaf Ebrahimi       {true, false, 32, UINT64_C(0xabcdabcd)},
124*f5c631daSSadaf Ebrahimi       {true, false, 32, UINT64_C(0x80000000)},
125*f5c631daSSadaf Ebrahimi       {true, false, 32, UINT64_C(0xffffffff)},
126*f5c631daSSadaf Ebrahimi   };
127*f5c631daSSadaf Ebrahimi 
128*f5c631daSSadaf Ebrahimi   UintIntTest<int64_t> test_i32[] = {
129*f5c631daSSadaf Ebrahimi       {true, true, 32, INT64_C(0)},
130*f5c631daSSadaf Ebrahimi       {true, true, 32, INT64_C(42)},
131*f5c631daSSadaf Ebrahimi       {false, true, 32, INT64_C(-42)},
132*f5c631daSSadaf Ebrahimi       {false, true, 32, INT64_C(-1)},
133*f5c631daSSadaf Ebrahimi       {true, true, 32, INT64_C(2147483647)},    // (1 << (32 - 1)) - 1
134*f5c631daSSadaf Ebrahimi       {false, true, 32, INT64_C(-2147483648)},  // -(1 << (32 - 1))
135*f5c631daSSadaf Ebrahimi   };
136*f5c631daSSadaf Ebrahimi 
137*f5c631daSSadaf Ebrahimi   UintIntTest<uint64_t> test_unsigned_higher_than_32[] = {
138*f5c631daSSadaf Ebrahimi       {false, false, 54, UINT64_C(0xabcdef9012345678)},
139*f5c631daSSadaf Ebrahimi       {true, false, 33, UINT64_C(0x100000000)},
140*f5c631daSSadaf Ebrahimi       {true, false, 62, UINT64_C(0x3fffffffffffffff)},
141*f5c631daSSadaf Ebrahimi       {true, false, 63, UINT64_C(0x7fffffffffffffff)},
142*f5c631daSSadaf Ebrahimi   };
143*f5c631daSSadaf Ebrahimi 
144*f5c631daSSadaf Ebrahimi   UintIntTest<int64_t> test_signed_higher_than_32[] = {
145*f5c631daSSadaf Ebrahimi       {true, true, 54, INT64_C(9007199254740991)},   // (1 << (54 - 1)) - 1
146*f5c631daSSadaf Ebrahimi       {true, false, 54, INT64_C(9007199254740992)},  // 1 << (54 - 1)
147*f5c631daSSadaf Ebrahimi       {true, true, 33, INT64_C(4294967295)},         // (1 << (33 - 1) - 1)
148*f5c631daSSadaf Ebrahimi       {false, true, 33, INT64_C(-4294967296)},       // -(1 << (33 - 1))
149*f5c631daSSadaf Ebrahimi   };
150*f5c631daSSadaf Ebrahimi 
151*f5c631daSSadaf Ebrahimi #define TEST_LIST(M)              \
152*f5c631daSSadaf Ebrahimi   M(test_little_values_unsigned)  \
153*f5c631daSSadaf Ebrahimi   M(test_little_values_signed)    \
154*f5c631daSSadaf Ebrahimi   M(test_u16)                     \
155*f5c631daSSadaf Ebrahimi   M(test_i16)                     \
156*f5c631daSSadaf Ebrahimi   M(test_u32)                     \
157*f5c631daSSadaf Ebrahimi   M(test_i32)                     \
158*f5c631daSSadaf Ebrahimi   M(test_unsigned_higher_than_32) \
159*f5c631daSSadaf Ebrahimi   M(test_signed_higher_than_32)
160*f5c631daSSadaf Ebrahimi 
161*f5c631daSSadaf Ebrahimi 
162*f5c631daSSadaf Ebrahimi #define TEST_UINT(test_vector)                                  \
163*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < ARRAY_SIZE(test_vector); i++) {      \
164*f5c631daSSadaf Ebrahimi     if (test_vector[i].is_uintn) {                              \
165*f5c631daSSadaf Ebrahimi       VIXL_CHECK(IsUintN(test_vector[i].n, test_vector[i].x));  \
166*f5c631daSSadaf Ebrahimi     } else {                                                    \
167*f5c631daSSadaf Ebrahimi       VIXL_CHECK(!IsUintN(test_vector[i].n, test_vector[i].x)); \
168*f5c631daSSadaf Ebrahimi     }                                                           \
169*f5c631daSSadaf Ebrahimi   }
170*f5c631daSSadaf Ebrahimi 
171*f5c631daSSadaf Ebrahimi #define TEST_INT(test_vector)                                  \
172*f5c631daSSadaf Ebrahimi   for (unsigned i = 0; i < ARRAY_SIZE(test_vector); i++) {     \
173*f5c631daSSadaf Ebrahimi     if (test_vector[i].is_intn) {                              \
174*f5c631daSSadaf Ebrahimi       VIXL_CHECK(IsIntN(test_vector[i].n, test_vector[i].x));  \
175*f5c631daSSadaf Ebrahimi     } else {                                                   \
176*f5c631daSSadaf Ebrahimi       VIXL_CHECK(!IsIntN(test_vector[i].n, test_vector[i].x)); \
177*f5c631daSSadaf Ebrahimi     }                                                          \
178*f5c631daSSadaf Ebrahimi   }
179*f5c631daSSadaf Ebrahimi 
180*f5c631daSSadaf Ebrahimi   TEST_LIST(TEST_UINT)
181*f5c631daSSadaf Ebrahimi   TEST_LIST(TEST_INT)
182*f5c631daSSadaf Ebrahimi 
183*f5c631daSSadaf Ebrahimi #undef TEST_UINT
184*f5c631daSSadaf Ebrahimi #undef TEST_INT
185*f5c631daSSadaf Ebrahimi 
186*f5c631daSSadaf Ebrahimi #undef TEST_LIST
187*f5c631daSSadaf Ebrahimi }
188*f5c631daSSadaf Ebrahimi 
189*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_iterator_api)190*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_iterator_api) {
191*f5c631daSSadaf Ebrahimi   // CPUFeaturesIterator does not fully satisfy the requirements of C++'s
192*f5c631daSSadaf Ebrahimi   // iterator concepts, but it should implement enough for some basic usage.
193*f5c631daSSadaf Ebrahimi 
194*f5c631daSSadaf Ebrahimi   // Arbitrary feature lists.
195*f5c631daSSadaf Ebrahimi   CPUFeatures f1(CPUFeatures::kFP, CPUFeatures::kNEON);
196*f5c631daSSadaf Ebrahimi   CPUFeatures f2(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kCRC32);
197*f5c631daSSadaf Ebrahimi   CPUFeatures f3;
198*f5c631daSSadaf Ebrahimi 
199*f5c631daSSadaf Ebrahimi   typedef CPUFeatures::const_iterator It;
200*f5c631daSSadaf Ebrahimi 
201*f5c631daSSadaf Ebrahimi   It it0;
202*f5c631daSSadaf Ebrahimi   It it1_neon(&f1, CPUFeatures::kNEON);
203*f5c631daSSadaf Ebrahimi   It it2_neon(&f2, CPUFeatures::kNEON);
204*f5c631daSSadaf Ebrahimi   It it2_crc32(&f2, CPUFeatures::kCRC32);
205*f5c631daSSadaf Ebrahimi   It it3(&f3);
206*f5c631daSSadaf Ebrahimi 
207*f5c631daSSadaf Ebrahimi   // Equality
208*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it0 == it0);
209*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it1_neon == it1_neon);
210*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it2_neon == it2_neon);
211*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it2_crc32 == it2_crc32);
212*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it3 == it3);
213*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it0 == it1_neon));
214*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it0 == it3));
215*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it1_neon == it2_neon));
216*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it1_neon == it2_crc32));
217*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it1_neon == it3));
218*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it2_neon == it2_crc32));
219*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it3 == it0));
220*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it3 == it1_neon));
221*f5c631daSSadaf Ebrahimi 
222*f5c631daSSadaf Ebrahimi   // Inequality
223*f5c631daSSadaf Ebrahimi   //   (a == b)  <->  !(a != b)
224*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it0 != it0));
225*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it1_neon != it1_neon));
226*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it2_neon != it2_neon));
227*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it2_crc32 != it2_crc32));
228*f5c631daSSadaf Ebrahimi   VIXL_CHECK(!(it3 != it3));
229*f5c631daSSadaf Ebrahimi   //   !(a == b)  <->  (a != b)
230*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it0 != it1_neon);
231*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it0 != it3);
232*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it1_neon != it2_neon);
233*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it1_neon != it2_crc32);
234*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it1_neon != it3);
235*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it2_neon != it2_crc32);
236*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it3 != it0);
237*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it3 != it1_neon);
238*f5c631daSSadaf Ebrahimi 
239*f5c631daSSadaf Ebrahimi   // Dereferenceable
240*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it0 == CPUFeatures::kNone);
241*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it1_neon == CPUFeatures::kNEON);
242*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_neon == CPUFeatures::kNEON);
243*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_crc32 == CPUFeatures::kCRC32);
244*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it3 == CPUFeatures::kNone);
245*f5c631daSSadaf Ebrahimi 
246*f5c631daSSadaf Ebrahimi #if __cplusplus >= 201103L
247*f5c631daSSadaf Ebrahimi   VIXL_STATIC_ASSERT(std::is_copy_constructible<It>::value);
248*f5c631daSSadaf Ebrahimi   VIXL_STATIC_ASSERT(std::is_copy_assignable<It>::value);
249*f5c631daSSadaf Ebrahimi   VIXL_STATIC_ASSERT(std::is_destructible<It>::value);
250*f5c631daSSadaf Ebrahimi #endif
251*f5c631daSSadaf Ebrahimi   // Copy constructable
252*f5c631daSSadaf Ebrahimi   It test0 = it0;
253*f5c631daSSadaf Ebrahimi   It test1 = it1_neon;
254*f5c631daSSadaf Ebrahimi   It test2(it2_neon);
255*f5c631daSSadaf Ebrahimi   VIXL_CHECK(test0 == It(NULL, CPUFeatures::kNone));
256*f5c631daSSadaf Ebrahimi   VIXL_CHECK(test1 == It(&f1, CPUFeatures::kNEON));
257*f5c631daSSadaf Ebrahimi   VIXL_CHECK(test2 == It(&f2, CPUFeatures::kNEON));
258*f5c631daSSadaf Ebrahimi 
259*f5c631daSSadaf Ebrahimi   // Copy assignable
260*f5c631daSSadaf Ebrahimi   test2 = it2_crc32;
261*f5c631daSSadaf Ebrahimi   VIXL_CHECK(test2 == It(&f2, CPUFeatures::kCRC32));
262*f5c631daSSadaf Ebrahimi 
263*f5c631daSSadaf Ebrahimi   // Incrementable
264*f5c631daSSadaf Ebrahimi   // - Incrementing has no effect on an empty CPUFeatures.
265*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it3++ == CPUFeatures::kNone);
266*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*(++it3) == CPUFeatures::kNone);
267*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it3 == It(&f3, CPUFeatures::kNone));
268*f5c631daSSadaf Ebrahimi   // - Incrementing moves to the next feature, wrapping around (through kNone).
269*f5c631daSSadaf Ebrahimi   //   This test will need to be updated if the Feature enum is reordered.
270*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_neon++ == CPUFeatures::kNEON);
271*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_neon++ == CPUFeatures::kCRC32);
272*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_neon++ == CPUFeatures::kNone);
273*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*it2_neon++ == CPUFeatures::kFP);
274*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it2_neon == It(&f2, CPUFeatures::kNEON));
275*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*(++it2_crc32) == CPUFeatures::kNone);
276*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*(++it2_crc32) == CPUFeatures::kFP);
277*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*(++it2_crc32) == CPUFeatures::kNEON);
278*f5c631daSSadaf Ebrahimi   VIXL_CHECK(*(++it2_crc32) == CPUFeatures::kCRC32);
279*f5c631daSSadaf Ebrahimi   VIXL_CHECK(it2_crc32 == It(&f2, CPUFeatures::kCRC32));
280*f5c631daSSadaf Ebrahimi }
281*f5c631daSSadaf Ebrahimi 
282*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_iterator_loops)283*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_iterator_loops) {
284*f5c631daSSadaf Ebrahimi   // Check that CPUFeaturesIterator can be used for some simple loops.
285*f5c631daSSadaf Ebrahimi 
286*f5c631daSSadaf Ebrahimi   // Arbitrary feature lists.
287*f5c631daSSadaf Ebrahimi   CPUFeatures f1(CPUFeatures::kFP, CPUFeatures::kNEON);
288*f5c631daSSadaf Ebrahimi   CPUFeatures f2(CPUFeatures::kFP, CPUFeatures::kNEON, CPUFeatures::kCRC32);
289*f5c631daSSadaf Ebrahimi   CPUFeatures f3;
290*f5c631daSSadaf Ebrahimi 
291*f5c631daSSadaf Ebrahimi   // This test will need to be updated if the Feature enum is reordered.
292*f5c631daSSadaf Ebrahimi 
293*f5c631daSSadaf Ebrahimi   std::vector<CPUFeatures::Feature> f1_list;
294*f5c631daSSadaf Ebrahimi   for (CPUFeatures::const_iterator it = f1.begin(); it != f1.end(); ++it) {
295*f5c631daSSadaf Ebrahimi     f1_list.push_back(*it);
296*f5c631daSSadaf Ebrahimi   }
297*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f1_list.size() == 2);
298*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f1_list[0] == CPUFeatures::kFP);
299*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f1_list[1] == CPUFeatures::kNEON);
300*f5c631daSSadaf Ebrahimi 
301*f5c631daSSadaf Ebrahimi   std::vector<CPUFeatures::Feature> f2_list;
302*f5c631daSSadaf Ebrahimi   for (CPUFeatures::const_iterator it = f2.begin(); it != f2.end(); ++it) {
303*f5c631daSSadaf Ebrahimi     f2_list.push_back(*it);
304*f5c631daSSadaf Ebrahimi   }
305*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list.size() == 3);
306*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list[0] == CPUFeatures::kFP);
307*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list[1] == CPUFeatures::kNEON);
308*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list[2] == CPUFeatures::kCRC32);
309*f5c631daSSadaf Ebrahimi 
310*f5c631daSSadaf Ebrahimi   std::vector<CPUFeatures::Feature> f3_list;
311*f5c631daSSadaf Ebrahimi   for (CPUFeatures::const_iterator it = f3.begin(); it != f3.end(); ++it) {
312*f5c631daSSadaf Ebrahimi     f3_list.push_back(*it);
313*f5c631daSSadaf Ebrahimi   }
314*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f3_list.size() == 0);
315*f5c631daSSadaf Ebrahimi 
316*f5c631daSSadaf Ebrahimi   std::vector<CPUFeatures::Feature> f2_list_cxx11;
317*f5c631daSSadaf Ebrahimi   for (auto&& feature : f2) {
318*f5c631daSSadaf Ebrahimi     f2_list_cxx11.push_back(feature);
319*f5c631daSSadaf Ebrahimi   }
320*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list_cxx11.size() == 3);
321*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list_cxx11[0] == CPUFeatures::kFP);
322*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list_cxx11[1] == CPUFeatures::kNEON);
323*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f2_list_cxx11[2] == CPUFeatures::kCRC32);
324*f5c631daSSadaf Ebrahimi 
325*f5c631daSSadaf Ebrahimi   std::vector<CPUFeatures::Feature> f3_list_cxx11;
326*f5c631daSSadaf Ebrahimi   for (auto&& feature : f3) {
327*f5c631daSSadaf Ebrahimi     f3_list_cxx11.push_back(feature);
328*f5c631daSSadaf Ebrahimi   }
329*f5c631daSSadaf Ebrahimi   VIXL_CHECK(f3_list_cxx11.size() == 0);
330*f5c631daSSadaf Ebrahimi }
331*f5c631daSSadaf Ebrahimi 
332*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_empty)333*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_empty) {
334*f5c631daSSadaf Ebrahimi   // A default-constructed CPUFeatures has no features enabled.
335*f5c631daSSadaf Ebrahimi   CPUFeatures features;
336*f5c631daSSadaf Ebrahimi   for (auto f : features) {
337*f5c631daSSadaf Ebrahimi     USE(f);
338*f5c631daSSadaf Ebrahimi     VIXL_ABORT();
339*f5c631daSSadaf Ebrahimi   }
340*f5c631daSSadaf Ebrahimi   VIXL_CHECK(features.HasNoFeatures());
341*f5c631daSSadaf Ebrahimi   VIXL_CHECK(features.Count() == 0);
342*f5c631daSSadaf Ebrahimi }
343*f5c631daSSadaf Ebrahimi 
344*f5c631daSSadaf Ebrahimi 
CPUFeaturesFormatHelper(const char * expected,const CPUFeatures & features)345*f5c631daSSadaf Ebrahimi static void CPUFeaturesFormatHelper(const char* expected,
346*f5c631daSSadaf Ebrahimi                                     const CPUFeatures& features) {
347*f5c631daSSadaf Ebrahimi   std::stringstream os;
348*f5c631daSSadaf Ebrahimi   os << features;
349*f5c631daSSadaf Ebrahimi   std::string os_str = os.str();
350*f5c631daSSadaf Ebrahimi   if (os_str != expected) {
351*f5c631daSSadaf Ebrahimi     std::cout << "Found: " << os_str << "\n";
352*f5c631daSSadaf Ebrahimi     std::cout << "Expected: " << expected << "\n";
353*f5c631daSSadaf Ebrahimi     VIXL_ABORT();
354*f5c631daSSadaf Ebrahimi   }
355*f5c631daSSadaf Ebrahimi }
356*f5c631daSSadaf Ebrahimi 
357*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_format)358*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_format) {
359*f5c631daSSadaf Ebrahimi   // Check that the debug output is complete and accurate.
360*f5c631daSSadaf Ebrahimi 
361*f5c631daSSadaf Ebrahimi   // Individual features.
362*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("", CPUFeatures(CPUFeatures::kNone));
363*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("FP", CPUFeatures(CPUFeatures::kFP));
364*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("NEON", CPUFeatures(CPUFeatures::kNEON));
365*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("AES", CPUFeatures(CPUFeatures::kAES));
366*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("Pmull1Q", CPUFeatures(CPUFeatures::kPmull1Q));
367*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("SHA1", CPUFeatures(CPUFeatures::kSHA1));
368*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("SHA2", CPUFeatures(CPUFeatures::kSHA2));
369*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("CRC32", CPUFeatures(CPUFeatures::kCRC32));
370*f5c631daSSadaf Ebrahimi 
371*f5c631daSSadaf Ebrahimi   // Combinations of (arbitrary) features.
372*f5c631daSSadaf Ebrahimi   // This test will need to be updated if the Feature enum is reordered.
373*f5c631daSSadaf Ebrahimi   CPUFeatures f(CPUFeatures::kFP, CPUFeatures::kNEON);
374*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("FP, NEON", f);
375*f5c631daSSadaf Ebrahimi   f.Combine(CPUFeatures::kCRC32);
376*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("FP, NEON, CRC32", f);
377*f5c631daSSadaf Ebrahimi   f.Combine(CPUFeatures::kFcma);
378*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("FP, NEON, CRC32, Fcma", f);
379*f5c631daSSadaf Ebrahimi   f.Combine(CPUFeatures::kSHA1);
380*f5c631daSSadaf Ebrahimi   CPUFeaturesFormatHelper("FP, NEON, CRC32, SHA1, Fcma", f);
381*f5c631daSSadaf Ebrahimi }
382*f5c631daSSadaf Ebrahimi 
383*f5c631daSSadaf Ebrahimi 
CPUFeaturesPredefinedResultCheckHelper(const std::set<CPUFeatures::Feature> & unexpected,const std::set<CPUFeatures::Feature> & expected)384*f5c631daSSadaf Ebrahimi static void CPUFeaturesPredefinedResultCheckHelper(
385*f5c631daSSadaf Ebrahimi     const std::set<CPUFeatures::Feature>& unexpected,
386*f5c631daSSadaf Ebrahimi     const std::set<CPUFeatures::Feature>& expected) {
387*f5c631daSSadaf Ebrahimi   // Print a helpful diagnostic before checking the result.
388*f5c631daSSadaf Ebrahimi   if (!unexpected.empty()) {
389*f5c631daSSadaf Ebrahimi     std::cout << "Unexpected features:\n";
390*f5c631daSSadaf Ebrahimi     for (auto f : unexpected) {
391*f5c631daSSadaf Ebrahimi       std::cout << "  " << f << "\n";
392*f5c631daSSadaf Ebrahimi     }
393*f5c631daSSadaf Ebrahimi   }
394*f5c631daSSadaf Ebrahimi   if (!expected.empty()) {
395*f5c631daSSadaf Ebrahimi     std::cout << "Missing features:\n";
396*f5c631daSSadaf Ebrahimi     for (auto f : expected) {
397*f5c631daSSadaf Ebrahimi       std::cout << "  " << f << "\n";
398*f5c631daSSadaf Ebrahimi     }
399*f5c631daSSadaf Ebrahimi   }
400*f5c631daSSadaf Ebrahimi   VIXL_CHECK(unexpected.empty() && expected.empty());
401*f5c631daSSadaf Ebrahimi }
402*f5c631daSSadaf Ebrahimi 
403*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_predefined_legacy)404*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_predefined_legacy) {
405*f5c631daSSadaf Ebrahimi   CPUFeatures features = CPUFeatures::AArch64LegacyBaseline();
406*f5c631daSSadaf Ebrahimi   std::set<CPUFeatures::Feature> unexpected;
407*f5c631daSSadaf Ebrahimi   std::set<CPUFeatures::Feature> expected;
408*f5c631daSSadaf Ebrahimi   expected.insert(CPUFeatures::kFP);
409*f5c631daSSadaf Ebrahimi   expected.insert(CPUFeatures::kNEON);
410*f5c631daSSadaf Ebrahimi   expected.insert(CPUFeatures::kCRC32);
411*f5c631daSSadaf Ebrahimi 
412*f5c631daSSadaf Ebrahimi   for (auto f : features) {
413*f5c631daSSadaf Ebrahimi     if (expected.erase(f) == 0) unexpected.insert(f);
414*f5c631daSSadaf Ebrahimi   }
415*f5c631daSSadaf Ebrahimi   CPUFeaturesPredefinedResultCheckHelper(unexpected, expected);
416*f5c631daSSadaf Ebrahimi }
417*f5c631daSSadaf Ebrahimi 
418*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_predefined_all)419*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_predefined_all) {
420*f5c631daSSadaf Ebrahimi   CPUFeatures features = CPUFeatures::All();
421*f5c631daSSadaf Ebrahimi   std::set<CPUFeatures::Feature> found;
422*f5c631daSSadaf Ebrahimi 
423*f5c631daSSadaf Ebrahimi   for (auto f : features) {
424*f5c631daSSadaf Ebrahimi     found.insert(f);
425*f5c631daSSadaf Ebrahimi   }
426*f5c631daSSadaf Ebrahimi   VIXL_CHECK(found.size() == CPUFeatures::kNumberOfFeatures);
427*f5c631daSSadaf Ebrahimi   VIXL_CHECK(found.size() == features.Count());
428*f5c631daSSadaf Ebrahimi }
429*f5c631daSSadaf Ebrahimi 
430*f5c631daSSadaf Ebrahimi // The CPUFeaturesScope constructor is templated, and needs an object which
431*f5c631daSSadaf Ebrahimi // implements `CPUFeatures* GetCPUFeatures()`. This is normally something like
432*f5c631daSSadaf Ebrahimi // the Assembler, but for the tests we use an architecture-independent wrapper.
433*f5c631daSSadaf Ebrahimi class GetCPUFeaturesWrapper {
434*f5c631daSSadaf Ebrahimi  public:
GetCPUFeaturesWrapper(CPUFeatures * cpu_features)435*f5c631daSSadaf Ebrahimi   explicit GetCPUFeaturesWrapper(CPUFeatures* cpu_features)
436*f5c631daSSadaf Ebrahimi       : cpu_features_(cpu_features) {}
437*f5c631daSSadaf Ebrahimi 
GetCPUFeatures() const438*f5c631daSSadaf Ebrahimi   CPUFeatures* GetCPUFeatures() const { return cpu_features_; }
439*f5c631daSSadaf Ebrahimi 
440*f5c631daSSadaf Ebrahimi  private:
441*f5c631daSSadaf Ebrahimi   CPUFeatures* cpu_features_;
442*f5c631daSSadaf Ebrahimi };
443*f5c631daSSadaf Ebrahimi 
TEST(CPUFeaturesScope)444*f5c631daSSadaf Ebrahimi TEST(CPUFeaturesScope) {
445*f5c631daSSadaf Ebrahimi   // Test that CPUFeaturesScope properly preserves state.
446*f5c631daSSadaf Ebrahimi 
447*f5c631daSSadaf Ebrahimi   CPUFeatures cpu(CPUFeatures::kCRC32, CPUFeatures::kSHA1, CPUFeatures::kAES);
448*f5c631daSSadaf Ebrahimi   GetCPUFeaturesWrapper top_level(&cpu);
449*f5c631daSSadaf Ebrahimi 
450*f5c631daSSadaf Ebrahimi   const CPUFeatures original_outer = cpu;
451*f5c631daSSadaf Ebrahimi 
452*f5c631daSSadaf Ebrahimi   {  // Test setting both new and existing features.
453*f5c631daSSadaf Ebrahimi     CPUFeaturesScope outer(&top_level, CPUFeatures::kSHA2, CPUFeatures::kAES);
454*f5c631daSSadaf Ebrahimi     VIXL_CHECK(outer.GetCPUFeatures() == &cpu);
455*f5c631daSSadaf Ebrahimi     VIXL_CHECK(cpu.Has(CPUFeatures::kCRC32,
456*f5c631daSSadaf Ebrahimi                        CPUFeatures::kSHA1,
457*f5c631daSSadaf Ebrahimi                        CPUFeatures::kSHA2,
458*f5c631daSSadaf Ebrahimi                        CPUFeatures::kAES));
459*f5c631daSSadaf Ebrahimi 
460*f5c631daSSadaf Ebrahimi     // Features can be added or removed directly, in the usual fashion.
461*f5c631daSSadaf Ebrahimi     // (The scope will restore their original status when it ends.)
462*f5c631daSSadaf Ebrahimi     cpu.Combine(CPUFeatures::kSHA1, CPUFeatures::kAtomics);
463*f5c631daSSadaf Ebrahimi     VIXL_CHECK(cpu.Has(CPUFeatures::kCRC32,
464*f5c631daSSadaf Ebrahimi                        CPUFeatures::kSHA1,
465*f5c631daSSadaf Ebrahimi                        CPUFeatures::kSHA2,
466*f5c631daSSadaf Ebrahimi                        CPUFeatures::kAES));
467*f5c631daSSadaf Ebrahimi     VIXL_CHECK(cpu.Has(CPUFeatures::kAtomics));
468*f5c631daSSadaf Ebrahimi 
469*f5c631daSSadaf Ebrahimi     cpu.Remove(CPUFeatures::kSHA2, CPUFeatures::kAES);
470*f5c631daSSadaf Ebrahimi     VIXL_CHECK(!cpu.Has(CPUFeatures::kSHA2, CPUFeatures::kAES));
471*f5c631daSSadaf Ebrahimi     VIXL_CHECK(cpu.Has(CPUFeatures::kCRC32,
472*f5c631daSSadaf Ebrahimi                        CPUFeatures::kSHA1,
473*f5c631daSSadaf Ebrahimi                        CPUFeatures::kAtomics));
474*f5c631daSSadaf Ebrahimi 
475*f5c631daSSadaf Ebrahimi     const CPUFeatures original_inner = cpu;
476*f5c631daSSadaf Ebrahimi 
477*f5c631daSSadaf Ebrahimi     // Scopes can be nested.
478*f5c631daSSadaf Ebrahimi     {
479*f5c631daSSadaf Ebrahimi       // A CPUFeaturesScope can be constructed from a CPUFeatures*, or any
480*f5c631daSSadaf Ebrahimi       // (non-local) object that implements `CPUFeatures* GetCPUFeatures()`.
481*f5c631daSSadaf Ebrahimi       // Typically, this would be an Assembler or MacroAssembler, but
482*f5c631daSSadaf Ebrahimi       // CPUFeatureScope itself provides this method, and allows the test to
483*f5c631daSSadaf Ebrahimi       // remain architecture-agnostic.
484*f5c631daSSadaf Ebrahimi 
485*f5c631daSSadaf Ebrahimi       CPUFeatures auth(CPUFeatures::kPAuth,
486*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthQARMA,
487*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthGeneric,
488*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthGenericQARMA,
489*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthEnhancedPAC2,
490*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthFPAC,
491*f5c631daSSadaf Ebrahimi                        CPUFeatures::kPAuthFPACCombined);
492*f5c631daSSadaf Ebrahimi 
493*f5c631daSSadaf Ebrahimi       CPUFeaturesScope inner(&outer, auth);
494*f5c631daSSadaf Ebrahimi       VIXL_CHECK(inner.GetCPUFeatures() == &cpu);
495*f5c631daSSadaf Ebrahimi       VIXL_CHECK(cpu.Has(auth.With(CPUFeatures::kCRC32,
496*f5c631daSSadaf Ebrahimi                                    CPUFeatures::kSHA1,
497*f5c631daSSadaf Ebrahimi                                    CPUFeatures::kAtomics)));
498*f5c631daSSadaf Ebrahimi     }
499*f5c631daSSadaf Ebrahimi     // Check for equivalence.
500*f5c631daSSadaf Ebrahimi     VIXL_CHECK(cpu.Has(original_inner));
501*f5c631daSSadaf Ebrahimi     VIXL_CHECK(original_inner.Has(cpu));
502*f5c631daSSadaf Ebrahimi   }
503*f5c631daSSadaf Ebrahimi 
504*f5c631daSSadaf Ebrahimi   {
505*f5c631daSSadaf Ebrahimi     // Scopes can be initialised with no features.
506*f5c631daSSadaf Ebrahimi     CPUFeaturesScope scope(&top_level);
507*f5c631daSSadaf Ebrahimi   }
508*f5c631daSSadaf Ebrahimi 
509*f5c631daSSadaf Ebrahimi   // Check for equivalence.
510*f5c631daSSadaf Ebrahimi   VIXL_CHECK(cpu.Has(original_outer));
511*f5c631daSSadaf Ebrahimi   VIXL_CHECK(original_outer.Has(cpu));
512*f5c631daSSadaf Ebrahimi }
513*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_infer_from_os)514*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_infer_from_os) {
515*f5c631daSSadaf Ebrahimi   // Test that CPUFeatures::InferFromOS functions on supported platforms.
516*f5c631daSSadaf Ebrahimi   CPUFeatures os;
517*f5c631daSSadaf Ebrahimi   VIXL_ASSERT(os.HasNoFeatures());
518*f5c631daSSadaf Ebrahimi   os = CPUFeatures::InferFromOS();
519*f5c631daSSadaf Ebrahimi 
520*f5c631daSSadaf Ebrahimi   // Every real platform has FP and NEON. However, InferFromOS does not support
521*f5c631daSSadaf Ebrahimi   // every platform, so we also have to tolerate empty results.
522*f5c631daSSadaf Ebrahimi   if (os.HasNoFeatures()) {
523*f5c631daSSadaf Ebrahimi     std::cout << "Warning: CPUFeatures::InferFromOS() returned no results.\n";
524*f5c631daSSadaf Ebrahimi   } else {
525*f5c631daSSadaf Ebrahimi     std::cout << "CPUFeatures::InferFromOS():\n  {" << os << "}\n";
526*f5c631daSSadaf Ebrahimi     VIXL_CHECK(os.Has(CPUFeatures::kFP));
527*f5c631daSSadaf Ebrahimi     VIXL_CHECK(os.Has(CPUFeatures::kNEON));
528*f5c631daSSadaf Ebrahimi   }
529*f5c631daSSadaf Ebrahimi }
530*f5c631daSSadaf Ebrahimi 
TEST(CPUFeatures_infer_from_id_registers)531*f5c631daSSadaf Ebrahimi TEST(CPUFeatures_infer_from_id_registers) {
532*f5c631daSSadaf Ebrahimi   CPUFeatures os_only =
533*f5c631daSSadaf Ebrahimi       CPUFeatures::InferFromOS(CPUFeatures::kDontQueryIDRegisters);
534*f5c631daSSadaf Ebrahimi   std::cout << "CPUFeatures::InferFromOS(kDontQueryIDRegisters):\n  {"
535*f5c631daSSadaf Ebrahimi             << os_only << "}\n";
536*f5c631daSSadaf Ebrahimi   if (os_only.Has(CPUFeatures::kIDRegisterEmulation)) {
537*f5c631daSSadaf Ebrahimi     CPUFeatures id_regs = CPUFeatures::InferFromIDRegisters();
538*f5c631daSSadaf Ebrahimi     std::cout << "CPUFeatures::InferFromIDRegisters():\n  {" << id_regs
539*f5c631daSSadaf Ebrahimi               << "}\n";
540*f5c631daSSadaf Ebrahimi     // The ID registers should return at least as many features as the OS
541*f5c631daSSadaf Ebrahimi     // information. This is intended to verify VIXL's InferFromIDRegisters
542*f5c631daSSadaf Ebrahimi     // logic, but it also relies on the OS presenting consistent information.
543*f5c631daSSadaf Ebrahimi     VIXL_CHECK(id_regs.Has(os_only));
544*f5c631daSSadaf Ebrahimi 
545*f5c631daSSadaf Ebrahimi     // The default InferFromOS should combine its results with
546*f5c631daSSadaf Ebrahimi     // InferFromIDRegisters.
547*f5c631daSSadaf Ebrahimi     CPUFeatures os_auto = CPUFeatures::InferFromOS();
548*f5c631daSSadaf Ebrahimi     CPUFeatures os_with_id_regs = os_only.With(id_regs);
549*f5c631daSSadaf Ebrahimi     // Check equivalence.
550*f5c631daSSadaf Ebrahimi     VIXL_CHECK(os_auto.Has(os_with_id_regs));
551*f5c631daSSadaf Ebrahimi     VIXL_CHECK(os_with_id_regs.Has(os_auto));
552*f5c631daSSadaf Ebrahimi   } else {
553*f5c631daSSadaf Ebrahimi     // Note: This message needs to match REGEXP_MISSING_FEATURES from
554*f5c631daSSadaf Ebrahimi     // tools/threaded_test.py.
555*f5c631daSSadaf Ebrahimi     std::cout << "SKIPPED: Missing features: { "
556*f5c631daSSadaf Ebrahimi               << CPUFeatures::kIDRegisterEmulation << " }\n";
557*f5c631daSSadaf Ebrahimi     std::cout << "This test requires the following features to run its "
558*f5c631daSSadaf Ebrahimi                  "generated code on this CPU: "
559*f5c631daSSadaf Ebrahimi               << CPUFeatures::kIDRegisterEmulation << "\n";
560*f5c631daSSadaf Ebrahimi   }
561*f5c631daSSadaf Ebrahimi }
562*f5c631daSSadaf Ebrahimi 
563*f5c631daSSadaf Ebrahimi }  // namespace vixl
564