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