Commit | Line | Data |
---|---|---|
6dc2ca62 MD |
1 | /* |
2 | * test-bitfield.c | |
3 | * | |
d79865b9 | 4 | * BabelTrace - bitfield test program |
6dc2ca62 | 5 | * |
de0ba614 | 6 | * Copyright 2010 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
6dc2ca62 MD |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License as published by | |
9cb421e5 | 10 | * the Free Software Foundation; under version 2 of the License. |
6dc2ca62 MD |
11 | * |
12 | * This program is distributed in the hope that it will be useful, | |
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | * GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
20 | */ | |
21 | ||
d79865b9 | 22 | #include <babeltrace/bitfield.h> |
47e0f2e2 MD |
23 | #include <time.h> |
24 | #include <stdlib.h> | |
6dc2ca62 MD |
25 | #include <stdio.h> |
26 | ||
1833a3d1 | 27 | #include <tap/tap.h> |
9e8e57d0 | 28 | |
6dc2ca62 MD |
29 | unsigned int glob; |
30 | ||
31 | /* | |
32 | * This function is only declared to show the size of a bitfield write in | |
33 | * objdump. | |
34 | */ | |
35 | void fct(void) | |
36 | { | |
47e0f2e2 | 37 | bt_bitfield_write(&glob, unsigned int, 12, 15, 0x12345678); |
6dc2ca62 MD |
38 | } |
39 | ||
40 | /* Test array size, in bytes */ | |
41 | #define TEST_LEN 128 | |
42 | #define NR_TESTS 10 | |
9e8e57d0 JG |
43 | #define SIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, signed" |
44 | #define UNSIGNED_TEST_DESC_FMT_STR "Writing and reading back 0x%X, unsigned" | |
45 | #define DIAG_FMT_STR "Failed reading value written \"%s\"-wise, with start=%i" \ | |
46 | " and length=%i. Read %llX" | |
6dc2ca62 MD |
47 | |
48 | unsigned int srcrand; | |
49 | ||
50 | #if defined(__i386) || defined(__x86_64) | |
51 | ||
52 | static inline int fls(int x) | |
53 | { | |
54 | int r; | |
55 | asm("bsrl %1,%0\n\t" | |
56 | "cmovzl %2,%0" | |
57 | : "=&r" (r) : "rm" (x), "rm" (-1)); | |
58 | return r + 1; | |
59 | } | |
60 | ||
61 | #elif defined(__PPC__) | |
62 | ||
63 | static __inline__ int fls(unsigned int x) | |
64 | { | |
65 | int lz; | |
66 | ||
67 | asm ("cntlzw %0,%1" : "=r" (lz) : "r" (x)); | |
68 | return 32 - lz; | |
69 | } | |
70 | ||
71 | #else | |
72 | ||
73 | static int fls(unsigned int x) | |
74 | { | |
75 | int r = 32; | |
76 | ||
77 | if (!x) | |
78 | return 0; | |
79 | if (!(x & 0xFFFF0000U)) { | |
80 | x <<= 16; | |
81 | r -= 16; | |
82 | } | |
83 | if (!(x & 0xFF000000U)) { | |
84 | x <<= 8; | |
85 | r -= 8; | |
86 | } | |
87 | if (!(x & 0xF0000000U)) { | |
88 | x <<= 4; | |
89 | r -= 4; | |
90 | } | |
91 | if (!(x & 0xC0000000U)) { | |
92 | x <<= 2; | |
93 | r -= 2; | |
94 | } | |
95 | if (!(x & 0x80000000U)) { | |
96 | x <<= 1; | |
97 | r -= 1; | |
98 | } | |
99 | return r; | |
100 | } | |
101 | ||
102 | #endif | |
103 | ||
47e0f2e2 MD |
104 | #define print_byte_array(c, len) \ |
105 | do { \ | |
106 | unsigned long i; \ | |
107 | \ | |
108 | for (i = 0; i < (len); i++) { \ | |
109 | printf("0x%X", (c)[i]); \ | |
110 | if (i != (len) - 1) \ | |
111 | printf(" "); \ | |
112 | } \ | |
113 | printf("\n"); \ | |
114 | } while (0) | |
115 | ||
116 | #define init_byte_array(c, len, val) \ | |
117 | do { \ | |
118 | unsigned long i; \ | |
119 | \ | |
120 | for (i = 0; i < (len); i++) \ | |
121 | (c)[i] = (val); \ | |
122 | } while (0) | |
6dc2ca62 | 123 | |
9e8e57d0 JG |
124 | #define check_result(ref, val, buffer, typename, start, len, \ |
125 | desc_fmt_str) \ | |
126 | ({ \ | |
127 | if ((val) != (ref)) { \ | |
128 | fail(desc_fmt_str, ref); \ | |
129 | diag(DIAG_FMT_STR, #typename, start, len, val); \ | |
130 | printf("# "); \ | |
131 | print_byte_array(buffer, TEST_LEN); \ | |
132 | } \ | |
133 | (val) != (ref); \ | |
134 | }) | |
135 | ||
136 | void run_test_unsigned(void) | |
6dc2ca62 | 137 | { |
e6c404d1 | 138 | unsigned int src, nrbits; |
6dc2ca62 MD |
139 | union { |
140 | unsigned char c[TEST_LEN]; | |
141 | unsigned short s[TEST_LEN/sizeof(unsigned short)]; | |
142 | unsigned int i[TEST_LEN/sizeof(unsigned int)]; | |
143 | unsigned long l[TEST_LEN/sizeof(unsigned long)]; | |
144 | unsigned long long ll[TEST_LEN/sizeof(unsigned long long)]; | |
145 | } target; | |
380d60b1 | 146 | unsigned long long readval; |
6dc2ca62 | 147 | unsigned int s, l; |
6dc2ca62 MD |
148 | |
149 | src = srcrand; | |
150 | nrbits = fls(src); | |
151 | ||
152 | for (s = 0; s < CHAR_BIT * TEST_LEN; s++) { | |
153 | for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) { | |
154 | init_byte_array(target.c, TEST_LEN, 0xFF); | |
47e0f2e2 MD |
155 | bt_bitfield_write(target.c, unsigned char, s, l, src); |
156 | bt_bitfield_read(target.c, unsigned char, s, l, &readval); | |
9e8e57d0 JG |
157 | if (check_result(src, readval, target.c, unsigned char, |
158 | s, l, UNSIGNED_TEST_DESC_FMT_STR)) { | |
159 | return; | |
6dc2ca62 MD |
160 | } |
161 | ||
162 | init_byte_array(target.c, TEST_LEN, 0xFF); | |
47e0f2e2 MD |
163 | bt_bitfield_write(target.s, unsigned short, s, l, src); |
164 | bt_bitfield_read(target.c, unsigned char, s, l, &readval); | |
9e8e57d0 JG |
165 | if (check_result(src, readval, target.c, unsigned short, |
166 | s, l, UNSIGNED_TEST_DESC_FMT_STR)) { | |
167 | return; | |
6dc2ca62 MD |
168 | } |
169 | ||
170 | init_byte_array(target.c, TEST_LEN, 0xFF); | |
47e0f2e2 MD |
171 | bt_bitfield_write(target.i, unsigned int, s, l, src); |
172 | bt_bitfield_read(target.c, unsigned char, s, l, &readval); | |
9e8e57d0 JG |
173 | if (check_result(src, readval, target.c, unsigned int, |
174 | s, l, UNSIGNED_TEST_DESC_FMT_STR)) { | |
175 | return; | |
6dc2ca62 MD |
176 | } |
177 | ||
178 | init_byte_array(target.c, TEST_LEN, 0xFF); | |
47e0f2e2 MD |
179 | bt_bitfield_write(target.l, unsigned long, s, l, src); |
180 | bt_bitfield_read(target.c, unsigned char, s, l, &readval); | |
9e8e57d0 JG |
181 | if (check_result(src, readval, target.c, unsigned long, |
182 | s, l, UNSIGNED_TEST_DESC_FMT_STR)) { | |
183 | return; | |
6dc2ca62 MD |
184 | } |
185 | ||
186 | init_byte_array(target.c, TEST_LEN, 0xFF); | |
47e0f2e2 MD |
187 | bt_bitfield_write(target.ll, unsigned long long, s, l, src); |
188 | bt_bitfield_read(target.c, unsigned char, s, l, &readval); | |
9e8e57d0 JG |
189 | if (check_result(src, readval, target.c, unsigned long long, |
190 | s, l, UNSIGNED_TEST_DESC_FMT_STR)) { | |
191 | return; | |
6dc2ca62 MD |
192 | } |
193 | } | |
194 | } | |
9e8e57d0 JG |
195 | |
196 | pass(UNSIGNED_TEST_DESC_FMT_STR, src); | |
6dc2ca62 MD |
197 | } |
198 | ||
9e8e57d0 | 199 | void run_test_signed(void) |
6dc2ca62 | 200 | { |
e6c404d1 | 201 | int src, nrbits; |
6dc2ca62 | 202 | union { |
47e0f2e2 | 203 | signed char c[TEST_LEN]; |
6dc2ca62 MD |
204 | short s[TEST_LEN/sizeof(short)]; |
205 | int i[TEST_LEN/sizeof(int)]; | |
206 | long l[TEST_LEN/sizeof(long)]; | |
207 | long long ll[TEST_LEN/sizeof(long long)]; | |
208 | } target; | |
380d60b1 | 209 | long long readval; |
6dc2ca62 | 210 | unsigned int s, l; |
6dc2ca62 MD |
211 | |
212 | src = srcrand; | |
213 | if (src & 0x80000000U) | |
214 | nrbits = fls(~src) + 1; /* Find least significant bit conveying sign */ | |
215 | else | |
216 | nrbits = fls(src) + 1; /* Keep sign at 0 */ | |
217 | ||
9e8e57d0 JG |
218 | for (s = 0; s < CHAR_BIT * TEST_LEN; s++) { |
219 | for (l = nrbits; l < (CHAR_BIT * TEST_LEN) - s; l++) { | |
6dc2ca62 | 220 | init_byte_array(target.c, TEST_LEN, 0x0); |
47e0f2e2 MD |
221 | bt_bitfield_write(target.c, signed char, s, l, src); |
222 | bt_bitfield_read(target.c, signed char, s, l, &readval); | |
9e8e57d0 JG |
223 | if (check_result(src, readval, target.c, signed char, |
224 | s, l, SIGNED_TEST_DESC_FMT_STR)) { | |
225 | return; | |
6dc2ca62 MD |
226 | } |
227 | ||
228 | init_byte_array(target.c, TEST_LEN, 0x0); | |
47e0f2e2 MD |
229 | bt_bitfield_write(target.s, short, s, l, src); |
230 | bt_bitfield_read(target.c, signed char, s, l, &readval); | |
9e8e57d0 JG |
231 | if (check_result(src, readval, target.c, short, |
232 | s, l, SIGNED_TEST_DESC_FMT_STR)) { | |
233 | return; | |
6dc2ca62 MD |
234 | } |
235 | ||
236 | init_byte_array(target.c, TEST_LEN, 0x0); | |
47e0f2e2 MD |
237 | bt_bitfield_write(target.i, int, s, l, src); |
238 | bt_bitfield_read(target.c, signed char, s, l, &readval); | |
9e8e57d0 JG |
239 | if (check_result(src, readval, target.c, int, |
240 | s, l, SIGNED_TEST_DESC_FMT_STR)) { | |
241 | return; | |
6dc2ca62 MD |
242 | } |
243 | ||
244 | init_byte_array(target.c, TEST_LEN, 0x0); | |
47e0f2e2 MD |
245 | bt_bitfield_write(target.l, long, s, l, src); |
246 | bt_bitfield_read(target.c, signed char, s, l, &readval); | |
9e8e57d0 JG |
247 | if (check_result(src, readval, target.c, long, |
248 | s, l, SIGNED_TEST_DESC_FMT_STR)) { | |
249 | return; | |
6dc2ca62 MD |
250 | } |
251 | ||
252 | init_byte_array(target.c, TEST_LEN, 0x0); | |
47e0f2e2 MD |
253 | bt_bitfield_write(target.ll, long long, s, l, src); |
254 | bt_bitfield_read(target.c, signed char, s, l, &readval); | |
9e8e57d0 JG |
255 | if (check_result(src, readval, target.c, long long, |
256 | s, l, SIGNED_TEST_DESC_FMT_STR)) { | |
257 | return; | |
6dc2ca62 MD |
258 | } |
259 | } | |
260 | } | |
9e8e57d0 JG |
261 | |
262 | pass(SIGNED_TEST_DESC_FMT_STR, src); | |
6dc2ca62 MD |
263 | } |
264 | ||
9e8e57d0 | 265 | void run_test(void) |
6dc2ca62 | 266 | { |
6dc2ca62 | 267 | int i; |
9e8e57d0 | 268 | plan_tests(NR_TESTS * 2 + 6); |
6dc2ca62 MD |
269 | |
270 | srand(time(NULL)); | |
271 | ||
272 | srcrand = 0; | |
9e8e57d0 | 273 | run_test_unsigned(); |
6dc2ca62 | 274 | srcrand = 0; |
9e8e57d0 JG |
275 | run_test_signed(); |
276 | ||
6dc2ca62 | 277 | srcrand = 1; |
9e8e57d0 JG |
278 | run_test_unsigned(); |
279 | ||
6dc2ca62 | 280 | srcrand = ~0U; |
9e8e57d0 JG |
281 | run_test_unsigned(); |
282 | ||
6dc2ca62 | 283 | srcrand = -1; |
9e8e57d0 JG |
284 | run_test_signed(); |
285 | ||
6dc2ca62 | 286 | srcrand = (int)0x80000000U; |
9e8e57d0 | 287 | run_test_signed(); |
6dc2ca62 MD |
288 | |
289 | for (i = 0; i < NR_TESTS; i++) { | |
290 | srcrand = rand(); | |
9e8e57d0 JG |
291 | run_test_unsigned(); |
292 | run_test_signed(); | |
6dc2ca62 | 293 | } |
6dc2ca62 MD |
294 | } |
295 | ||
9e8e57d0 JG |
296 | static |
297 | int print_encodings(unsigned long src, unsigned int shift, unsigned int len) | |
6dc2ca62 | 298 | { |
6dc2ca62 MD |
299 | union { |
300 | unsigned char c[8]; | |
301 | unsigned short s[4]; | |
302 | unsigned int i[2]; | |
303 | unsigned long l[2]; | |
304 | unsigned long long ll[1]; | |
305 | } target; | |
380d60b1 | 306 | unsigned long long readval; |
6dc2ca62 | 307 | |
9e8e57d0 | 308 | init_byte_array(target.c, 8, 0xFF); |
47e0f2e2 | 309 | bt_bitfield_write(target.c, unsigned char, shift, len, src); |
6dc2ca62 MD |
310 | printf("bytewise\n"); |
311 | print_byte_array(target.c, 8); | |
312 | ||
9e8e57d0 | 313 | init_byte_array(target.c, 8, 0xFF); |
47e0f2e2 | 314 | bt_bitfield_write(target.s, unsigned short, shift, len, src); |
6dc2ca62 MD |
315 | printf("shortwise\n"); |
316 | print_byte_array(target.c, 8); | |
317 | ||
9e8e57d0 | 318 | init_byte_array(target.c, 8, 0xFF); |
47e0f2e2 | 319 | bt_bitfield_write(target.i, unsigned int, shift, len, src); |
6dc2ca62 MD |
320 | printf("intwise\n"); |
321 | print_byte_array(target.c, 8); | |
322 | ||
9e8e57d0 | 323 | init_byte_array(target.c, 8, 0xFF); |
47e0f2e2 | 324 | bt_bitfield_write(target.l, unsigned long, shift, len, src); |
6dc2ca62 MD |
325 | printf("longwise\n"); |
326 | print_byte_array(target.c, 8); | |
327 | ||
9e8e57d0 | 328 | init_byte_array(target.c, 8, 0xFF); |
47e0f2e2 | 329 | bt_bitfield_write(target.ll, unsigned long long, shift, len, src); |
6dc2ca62 MD |
330 | printf("lluwise\n"); |
331 | print_byte_array(target.c, 8); | |
332 | ||
47e0f2e2 | 333 | bt_bitfield_read(target.c, unsigned char, shift, len, &readval); |
6dc2ca62 | 334 | printf("read: %llX\n", readval); |
9e8e57d0 | 335 | print_byte_array(target.c, 8); |
6dc2ca62 | 336 | |
9e8e57d0 JG |
337 | return 0; |
338 | } | |
339 | ||
340 | int main(int argc, char **argv) | |
341 | { | |
342 | if (argc > 1) { | |
343 | /* Print encodings */ | |
344 | unsigned long src; | |
345 | unsigned int shift, len; | |
346 | ||
347 | src = atoi(argv[1]); | |
348 | if (argc > 2) | |
349 | shift = atoi(argv[2]); | |
350 | else | |
351 | shift = 12; | |
352 | if (argc > 3) | |
353 | len = atoi(argv[3]); | |
354 | else | |
355 | len = 40; | |
356 | return print_encodings(src, shift, len); | |
357 | } | |
6dc2ca62 | 358 | |
9e8e57d0 JG |
359 | /* Run tap-formated tests */ |
360 | run_test(); | |
361 | return exit_status(); | |
6dc2ca62 | 362 | } |