VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstRTArmv8.cpp@ 103005

Last change on this file since 103005 was 101613, checked in by vboxsync, 13 months ago

tstRTArmv8: Do random check of 64-bit range of masks. bugref:10371

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.2 KB
Line 
1/* $Id: tstRTArmv8.cpp 101613 2023-10-27 08:41:10Z vboxsync $ */
2/** @file
3 * IPRT Testcase - armv8.h inline functions.
4 */
5
6/*
7 * Copyright (C) 2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/asm.h> /** @todo fix me! */
42#include <iprt/armv8.h>
43
44#include <iprt/test.h>
45#include <iprt/rand.h>
46#include <iprt/stream.h>
47#include <iprt/sort.h>
48
49
50/*********************************************************************************************************************************
51* Defined Constants And Macros *
52*********************************************************************************************************************************/
53static unsigned g_cVerbosity = 0;
54
55
56const char *tobin(uint64_t uValue, unsigned cchWidth, char *pszBuf)
57{
58 char *psz = pszBuf;
59 while (cchWidth-- > 0)
60 *psz++ = (uValue & RT_BIT_64(cchWidth)) ? '1' : '0';
61 *psz = '\0';
62 return pszBuf;
63}
64
65
66/** @callback_method_impl{FNRTSORTCMP} */
67static DECLCALLBACK(int) cmpu32(void const *pvElement1, void const *pvElement2, void *pvUser)
68{
69 RT_NOREF(pvUser);
70 if (*(uint32_t const *)pvElement1 < *(uint32_t const *)pvElement2)
71 return -1;
72 if (*(uint32_t const *)pvElement1 > *(uint32_t const *)pvElement2)
73 return 1;
74 return 0;
75}
76
77
78/** @callback_method_impl{FNRTSORTCMP} */
79static DECLCALLBACK(int) cmpu64(void const *pvElement1, void const *pvElement2, void *pvUser)
80{
81 RT_NOREF(pvUser);
82 if (*(uint64_t const *)pvElement1 < *(uint64_t const *)pvElement2)
83 return -1;
84 if (*(uint64_t const *)pvElement1 > *(uint64_t const *)pvElement2)
85 return 1;
86 return 0;
87}
88
89
90static unsigned BinarySearchU64(uint64_t uValue, uint64_t const *pauEntries, unsigned idxEnd)
91{
92 unsigned idxStart = 0;
93 for (;;)
94 {
95 unsigned const idx = (idxEnd - idxStart) / 2 + idxStart;
96 uint64_t const uEntry = pauEntries[idx];
97 if (uValue < uEntry)
98 {
99 if (idx > idxStart)
100 idxEnd = idx;
101 else
102 return ~0U;
103 }
104 else if (uValue > uEntry)
105 {
106 if (idx + 1 < idxEnd)
107 idxStart = idx + 1;
108 else
109 return ~0U;
110 }
111 else
112 return idx;
113 }
114}
115
116
117void tstLogicalMask32(void)
118{
119 RTTestISub("32-bit logical masks");
120 static uint32_t s_auValidMasks[1312];
121 unsigned cValidMasks = 0;
122
123 /* Test all legal combinations, both directions. */
124 char szMask[128];
125 char szImmR[32];
126 char szImmS[32];
127 uint32_t uImmSElmnLength = 0x3c;
128 for (unsigned cBitsElementLog2 = 1; cBitsElementLog2 <= 5; cBitsElementLog2++)
129 {
130 unsigned const cBitsElement = 1U << cBitsElementLog2;
131 for (unsigned cOneBits = 0; cOneBits < cBitsElement - 1; cOneBits++)
132 {
133 for (unsigned cRotations = 0; cRotations < cBitsElement; cRotations++)
134 {
135 uint32_t const uImmS = cOneBits | uImmSElmnLength;
136 uint32_t const uMask = Armv8A64ConvertImmRImmS2Mask32(uImmS, cRotations);
137 RTTESTI_CHECK_RETV(cValidMasks < RT_ELEMENTS(s_auValidMasks));
138 s_auValidMasks[cValidMasks++] = uMask;
139
140 if (g_cVerbosity > 1)
141 RTPrintf("%08x %s size=%02u length=%02u rotation=%02u N=%u immr=%s imms=%s\n",
142 uMask, tobin(uMask, 32, szMask), cBitsElement, cOneBits, cRotations, 0,
143 tobin(cRotations, 6, szImmR), tobin(uImmS, 6, szImmS));
144
145 uint32_t uImmSRev = UINT32_MAX;
146 uint32_t uImmRRev = UINT32_MAX;
147 if (!Armv8A64ConvertMask32ToImmRImmS(uMask, &uImmSRev, &uImmRRev))
148 RTTestIFailed("Armv8A64ConvertMask32ToImmRImmS: failed for uMask=%#x (expected immS=%#x immR=%#x)\n",
149 uMask, uImmS, cRotations);
150 else if (uImmSRev != uImmS || uImmRRev != cRotations)
151 RTTestIFailed("Armv8A64ConvertMask32ToImmRImmS: incorrect results for uMask=%#x: immS=%#x immR=%#x, expected %#x & %#x\n",
152 uMask, uImmSRev, uImmRRev, uImmS, cRotations);
153 }
154 }
155 uImmSElmnLength = (uImmSElmnLength << 1) & 0x3f;
156 }
157
158 /* Now the other way around. */
159 RTSortShell(s_auValidMasks, cValidMasks, sizeof(s_auValidMasks[0]), cmpu32, NULL);
160 unsigned iValidMask = 0;
161 uint32_t uNextValidMask = s_auValidMasks[iValidMask];
162 uint32_t uMask = 0;
163 do
164 {
165 uint32_t uImmSRev = UINT32_MAX;
166 uint32_t uImmRRev = UINT32_MAX;
167 if (!Armv8A64ConvertMask32ToImmRImmS(uMask, &uImmSRev, &uImmRRev))
168 {
169 if (RT_LIKELY(uMask < uNextValidMask || iValidMask >= cValidMasks))
170 { }
171 else
172 {
173 RTTestIFailed("uMask=%#x - false negative\n", uMask);
174 break;
175 }
176 }
177 else if (RT_LIKELY(uMask == uNextValidMask && iValidMask < cValidMasks))
178 {
179 if (iValidMask + 1 < cValidMasks)
180 uNextValidMask = s_auValidMasks[++iValidMask];
181 else
182 {
183 iValidMask = cValidMasks;
184 uNextValidMask = UINT32_MAX;
185 }
186 }
187 else
188 {
189 RTTestIFailed("uMask=%#x - false positive\n", uMask);
190 break;
191 }
192 } while (uMask++ < UINT32_MAX);
193}
194
195
196void tstLogicalMask64(void)
197{
198 RTTestISub("64-bit logical masks");
199 static uint64_t s_auValidMasks[5376];
200 unsigned cValidMasks = 0;
201
202 /* Test all legal combinations, both directions. */
203 char szMask[128];
204 char szImmR[32];
205 char szImmS[32];
206 uint32_t uImmSElmnLength = 0x3c;
207 for (unsigned cBitsElementLog2 = 1; cBitsElementLog2 <= 6; cBitsElementLog2++)
208 {
209 unsigned const cBitsElement = 1U << cBitsElementLog2;
210 for (unsigned cOneBits = 0; cOneBits < cBitsElement - 1; cOneBits++)
211 {
212 for (unsigned cRotations = 0; cRotations < cBitsElement; cRotations++)
213 {
214 uint32_t const uImmS = cOneBits | uImmSElmnLength;
215 uint64_t const uMask = Armv8A64ConvertImmRImmS2Mask64(uImmS, cRotations);
216 RTTESTI_CHECK_RETV(cValidMasks < RT_ELEMENTS(s_auValidMasks));
217 s_auValidMasks[cValidMasks++] = uMask;
218
219 if (g_cVerbosity > 1)
220 RTPrintf("%016llx %s size=%02u length=%02u rotation=%02u N=%u immr=%s imms=%s\n",
221 uMask, tobin(uMask, 64, szMask), cBitsElement, cOneBits, cRotations, !!(uImmSElmnLength & 0x40),
222 tobin(cRotations, 6, szImmR), tobin(uImmS, 6, szImmS));
223
224 uint32_t uImmSRev = UINT32_MAX;
225 uint32_t uImmRRev = UINT32_MAX;
226 if (!Armv8A64ConvertMask64ToImmRImmS(uMask, &uImmSRev, &uImmRRev))
227 RTTestIFailed("Armv8A64ConvertMask64ToImmRImmS: failed for uMask=%#llx (expected immS=%#x immR=%#x)\n",
228 uMask, uImmS, cRotations);
229 else if (uImmSRev != uImmS || uImmRRev != cRotations)
230 RTTestIFailed("Armv8A64ConvertMask64ToImmRImmS: incorrect results for uMask=%#llx: immS=%#x immR=%#x, expected %#x & %#x\n",
231 uMask, uImmSRev, uImmRRev, uImmS, cRotations);
232 }
233 }
234 uImmSElmnLength = (uImmSElmnLength << 1) & 0x3f;
235 if (cBitsElementLog2 == 5)
236 uImmSElmnLength = 0x40;
237 }
238
239 /* Now the other way around, using random masks. */
240 RTSortShell(s_auValidMasks, cValidMasks, sizeof(s_auValidMasks[0]), cmpu64, NULL);
241
242 for (unsigned iRand = 0; iRand < _32M; iRand++)
243 {
244 uint64_t const uMask = RTRandU64();
245 unsigned const idxMask = BinarySearchU64(uMask, s_auValidMasks, cValidMasks);
246 uint32_t uImmSRev = UINT32_MAX;
247 uint32_t uImmRRev = UINT32_MAX;
248 if (!Armv8A64ConvertMask64ToImmRImmS(uMask, &uImmSRev, &uImmRRev))
249 {
250 if (RT_LIKELY(idxMask == ~0U))
251 { }
252 else
253 {
254 RTTestIFailed("uMask=%#018llx - false negative\n", uMask);
255 break;
256 }
257 }
258 else if (RT_LIKELY(idxMask < cValidMasks))
259 { /* likely */ }
260 else
261 {
262 RTTestIFailed("uMask=%#018llx - false positive\n", uMask);
263 break;
264 }
265 }
266}
267
268
269int main()
270{
271 RTTEST hTest;
272 RTEXITCODE rcExit = RTTestInitAndCreate("tstRTArmv8", &hTest);
273 if (rcExit != RTEXITCODE_SUCCESS)
274 return rcExit;
275
276 tstLogicalMask32();
277 tstLogicalMask64();
278
279 return RTTestSummaryAndDestroy(hTest);
280}
281
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette