11176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 21176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Copyright © 2012 Siarhei Siamashka <siarhei.siamashka@gmail.com> 31176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 41176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Based on the public domain implementation of small noncryptographic PRNG 51176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * authored by Bob Jenkins: http://burtleburtle.net/bob/rand/smallprng.html 61176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 71176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Permission is hereby granted, free of charge, to any person obtaining a 81176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * copy of this software and associated documentation files (the "Software"), 91176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to deal in the Software without restriction, including without limitation 101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * the rights to use, copy, modify, merge, publish, distribute, sublicense, 111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * and/or sell copies of the Software, and to permit persons to whom the 121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software is furnished to do so, subject to the following conditions: 131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * The above copyright notice and this permission notice (including the next 151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * paragraph) shall be included in all copies or substantial portions of the 161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Software. 171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * DEALINGS IN THE SOFTWARE. 251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "utils.h" 281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include "utils-prng.h" 291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#if defined(GCC_VECTOR_EXTENSIONS_SUPPORTED) && defined(__SSE2__) 311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#include <xmmintrin.h> 321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 341176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid smallprng_srand_r (smallprng_t *x, uint32_t seed) 351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t i; 371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->a = 0xf1ea5eed, x->b = x->c = x->d = seed; 381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < 20; ++i) 391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_rand_r (x); 401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Set a 32-bit seed for PRNG 441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * 451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * LCG is used here for generating independent seeds for different 461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * smallprng instances (in the case if smallprng is also used for 471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * generating these seeds, "Big Crush" test from TestU01 detects 481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * some problems in the glued 'prng_rand_128_r' output data). 491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Actually we might be even better using some cryptographic 501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * hash for this purpose, but LCG seems to be also enough for 511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * passing "Big Crush". 521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 531176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid prng_srand_r (prng_t *x, uint32_t seed) 541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED 561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int i; 571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_data_t dummy; 581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p0, seed); 591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->a[0] = x->a[1] = x->a[2] = x->a[3] = 0xf1ea5eed; 601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->b[0] = x->c[0] = x->d[0] = (seed = seed * 1103515245 + 12345); 611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->b[1] = x->c[1] = x->d[1] = (seed = seed * 1103515245 + 12345); 621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->b[2] = x->c[2] = x->d[2] = (seed = seed * 1103515245 + 12345); 631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck x->b[3] = x->c[3] = x->d[3] = (seed = seed * 1103515245 + 12345); 641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck for (i = 0; i < 20; ++i) 651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_r (x, &dummy); 661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else 671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p0, seed); 681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p1, (seed = seed * 1103515245 + 12345)); 691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p2, (seed = seed * 1103515245 + 12345)); 701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p3, (seed = seed * 1103515245 + 12345)); 711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck smallprng_srand_r (&x->p4, (seed = seed * 1103515245 + 12345)); 721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 751176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void 761176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstore_rand_128_data (void *addr, prng_rand_128_data_t *d, int aligned) 771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED 791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (aligned) 801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *(uint8x16 *)addr = d->vb; 821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return; 831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef __SSE2__ 871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* workaround for http://gcc.gnu.org/PR55614 */ 881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck _mm_storeu_si128 (addr, _mm_loadu_si128 ((__m128i *)d)); 891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck return; 901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* we could try something better for unaligned writes (packed attribute), 941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * but GCC is not very reliable: http://gcc.gnu.org/PR55454 */ 951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck memcpy (addr, d, 16); 961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Helper function and the actual code for "prng_randmemset_r" function 1001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 1011176bdada62cabc6ec4b0308a930e83b679d5d36John Reckstatic force_inline void 1021176bdada62cabc6ec4b0308a930e83b679d5d36John Reckrandmemset_internal (prng_t *prng, 1031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint8_t *buf, 1041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck size_t size, 1051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_randmemset_flags_t flags, 1061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int aligned) 1071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 1081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_t local_prng = *prng; 1091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_data_t randdata; 1101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck size_t i; 1111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (size >= 16) 1131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_data_t t; 1151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags == 0) 1161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_r (&local_prng, &randdata); 1181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 1201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_r (&local_prng, &t); 1221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_rand_128_r (&local_prng, &randdata); 1231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED 1241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_FF) 1251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const uint8x16 const_C0 = 1271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 1291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0 1301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck }; 1311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.vb |= (t.vb >= const_C0); 1321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_00) 1341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const uint8x16 const_40 = 1361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 1381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 1391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck }; 1401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.vb &= (t.vb >= const_40); 1411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_FFFFFFFF) 1431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const uint32x4 const_C0000000 = 1451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0xC0000000, 0xC0000000, 0xC0000000, 0xC0000000 1471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck }; 1481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.vw |= ((t.vw << 30) >= const_C0000000); 1491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_00000000) 1511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const uint32x4 const_40000000 = 1531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0x40000000, 0x40000000, 0x40000000, 0x40000000 1551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck }; 1561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.vw &= ((t.vw << 30) >= const_40000000); 1571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else 1591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck #define PROCESS_ONE_LANE(i) \ 1601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_FF) \ 1611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { \ 1621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t mask_ff = (t.w[i] & (t.w[i] << 1)) & 0x80808080; \ 1631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_ff |= mask_ff >> 1; \ 1641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_ff |= mask_ff >> 2; \ 1651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_ff |= mask_ff >> 4; \ 1661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.w[i] |= mask_ff; \ 1671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } \ 1681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_00) \ 1691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { \ 1701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint32_t mask_00 = (t.w[i] | (t.w[i] << 1)) & 0x80808080; \ 1711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_00 |= mask_00 >> 1; \ 1721176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_00 |= mask_00 >> 2; \ 1731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck mask_00 |= mask_00 >> 4; \ 1741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.w[i] &= mask_00; \ 1751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } \ 1761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_FFFFFFFF) \ 1771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { \ 1781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t mask_ff = ((t.w[i] << 30) & (t.w[i] << 31)) & \ 1791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0x80000000; \ 1801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.w[i] |= mask_ff >> 31; \ 1811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } \ 1821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags & RANDMEMSET_MORE_00000000) \ 1831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { \ 1841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck int32_t mask_00 = ((t.w[i] << 30) | (t.w[i] << 31)) & \ 1851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 0x80000000; \ 1861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.w[i] &= mask_00 >> 31; \ 1871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 1891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PROCESS_ONE_LANE (0) 1901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PROCESS_ONE_LANE (1) 1911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PROCESS_ONE_LANE (2) 1921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck PROCESS_ONE_LANE (3) 1931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 1941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 1951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (is_little_endian ()) 1961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 1971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck store_rand_128_data (buf, &randdata, aligned); 1981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck buf += 16; 1991176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2001176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 2011176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2021176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#ifdef GCC_VECTOR_EXTENSIONS_SUPPORTED 2031176bdada62cabc6ec4b0308a930e83b679d5d36John Reck const uint8x16 bswap_shufflemask = 2041176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2051176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12 2061176bdada62cabc6ec4b0308a930e83b679d5d36John Reck }; 2071176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randdata.vb = __builtin_shuffle (randdata.vb, bswap_shufflemask); 2081176bdada62cabc6ec4b0308a930e83b679d5d36John Reck store_rand_128_data (buf, &randdata, aligned); 2091176bdada62cabc6ec4b0308a930e83b679d5d36John Reck buf += 16; 2101176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#else 2111176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint8_t t1, t2, t3, t4; 2121176bdada62cabc6ec4b0308a930e83b679d5d36John Reck #define STORE_ONE_LANE(i) \ 2131176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t1 = randdata.b[i * 4 + 3]; \ 2141176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t2 = randdata.b[i * 4 + 2]; \ 2151176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t3 = randdata.b[i * 4 + 1]; \ 2161176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t4 = randdata.b[i * 4 + 0]; \ 2171176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buf++ = t1; \ 2181176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buf++ = t2; \ 2191176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buf++ = t3; \ 2201176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *buf++ = t4; 2211176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2221176bdada62cabc6ec4b0308a930e83b679d5d36John Reck STORE_ONE_LANE (0) 2231176bdada62cabc6ec4b0308a930e83b679d5d36John Reck STORE_ONE_LANE (1) 2241176bdada62cabc6ec4b0308a930e83b679d5d36John Reck STORE_ONE_LANE (2) 2251176bdada62cabc6ec4b0308a930e83b679d5d36John Reck STORE_ONE_LANE (3) 2261176bdada62cabc6ec4b0308a930e83b679d5d36John Reck#endif 2271176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2281176bdada62cabc6ec4b0308a930e83b679d5d36John Reck size -= 16; 2291176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2301176bdada62cabc6ec4b0308a930e83b679d5d36John Reck i = 0; 2311176bdada62cabc6ec4b0308a930e83b679d5d36John Reck while (i < size) 2321176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2331176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint8_t randbyte = prng_rand_r (&local_prng) & 0xFF; 2341176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags != 0) 2351176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2361176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint8_t t = prng_rand_r (&local_prng) & 0xFF; 2371176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((flags & RANDMEMSET_MORE_FF) && (t >= 0xC0)) 2381176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randbyte = 0xFF; 2391176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((flags & RANDMEMSET_MORE_00) && (t < 0x40)) 2401176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randbyte = 0x00; 2411176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (i % 4 == 0 && i + 4 <= size) 2421176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2431176bdada62cabc6ec4b0308a930e83b679d5d36John Reck t = prng_rand_r (&local_prng) & 0xFF; 2441176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((flags & RANDMEMSET_MORE_FFFFFFFF) && (t >= 0xC0)) 2451176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2461176bdada62cabc6ec4b0308a930e83b679d5d36John Reck memset(&buf[i], 0xFF, 4); 2471176bdada62cabc6ec4b0308a930e83b679d5d36John Reck i += 4; 2481176bdada62cabc6ec4b0308a930e83b679d5d36John Reck continue; 2491176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2501176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((flags & RANDMEMSET_MORE_00000000) && (t < 0x40)) 2511176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2521176bdada62cabc6ec4b0308a930e83b679d5d36John Reck memset(&buf[i], 0x00, 4); 2531176bdada62cabc6ec4b0308a930e83b679d5d36John Reck i += 4; 2541176bdada62cabc6ec4b0308a930e83b679d5d36John Reck continue; 2551176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2561176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2571176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2581176bdada62cabc6ec4b0308a930e83b679d5d36John Reck buf[i] = randbyte; 2591176bdada62cabc6ec4b0308a930e83b679d5d36John Reck i++; 2601176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2611176bdada62cabc6ec4b0308a930e83b679d5d36John Reck *prng = local_prng; 2621176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 2631176bdada62cabc6ec4b0308a930e83b679d5d36John Reck 2641176bdada62cabc6ec4b0308a930e83b679d5d36John Reck/* 2651176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * Fill memory buffer with random data. Flags argument may be used 2661176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * to tweak some statistics properties: 2671176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * RANDMEMSET_MORE_00 - set ~25% of bytes to 0x00 2681176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * RANDMEMSET_MORE_FF - set ~25% of bytes to 0xFF 2691176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * RANDMEMSET_MORE_00000000 - ~25% chance for 00000000 4-byte clusters 2701176bdada62cabc6ec4b0308a930e83b679d5d36John Reck * RANDMEMSET_MORE_FFFFFFFF - ~25% chance for FFFFFFFF 4-byte clusters 2711176bdada62cabc6ec4b0308a930e83b679d5d36John Reck */ 2721176bdada62cabc6ec4b0308a930e83b679d5d36John Reckvoid prng_randmemset_r (prng_t *prng, 2731176bdada62cabc6ec4b0308a930e83b679d5d36John Reck void *voidbuf, 2741176bdada62cabc6ec4b0308a930e83b679d5d36John Reck size_t size, 2751176bdada62cabc6ec4b0308a930e83b679d5d36John Reck prng_randmemset_flags_t flags) 2761176bdada62cabc6ec4b0308a930e83b679d5d36John Reck{ 2771176bdada62cabc6ec4b0308a930e83b679d5d36John Reck uint8_t *buf = (uint8_t *)voidbuf; 2781176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if ((uintptr_t)buf & 15) 2791176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2801176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* unaligned buffer */ 2811176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags == 0) 2821176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, 0, 0); 2831176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else if (flags == RANDMEMSET_MORE_00_AND_FF) 2841176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 0); 2851176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 2861176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, flags, 0); 2871176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2881176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 2891176bdada62cabc6ec4b0308a930e83b679d5d36John Reck { 2901176bdada62cabc6ec4b0308a930e83b679d5d36John Reck /* aligned buffer */ 2911176bdada62cabc6ec4b0308a930e83b679d5d36John Reck if (flags == 0) 2921176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, 0, 1); 2931176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else if (flags == RANDMEMSET_MORE_00_AND_FF) 2941176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, RANDMEMSET_MORE_00_AND_FF, 1); 2951176bdada62cabc6ec4b0308a930e83b679d5d36John Reck else 2961176bdada62cabc6ec4b0308a930e83b679d5d36John Reck randmemset_internal (prng, buf, size, flags, 1); 2971176bdada62cabc6ec4b0308a930e83b679d5d36John Reck } 2981176bdada62cabc6ec4b0308a930e83b679d5d36John Reck} 299