1/* 2 * @TAG(OTHER_MIT) 3 */ 4/* 5 * Copyright �� 2005-2014 Rich Felker, et al. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject to 13 * the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27#include "util.h" 28 29void *__sel4runtime_memset(void *dest, int c, sel4runtime_size_t n) 30{ 31 unsigned char *s = dest; 32 sel4runtime_size_t k; 33 34 /* Fill head and tail with minimal branching. Each 35 * conditional ensures that all the subsequently used 36 * offsets are well-defined and in the dest region. */ 37 38 if (!n) { 39 return dest; 40 } 41 s[0] = s[n - 1] = c; 42 if (n <= 2) { 43 return dest; 44 } 45 s[1] = s[n - 2] = c; 46 s[2] = s[n - 3] = c; 47 if (n <= 6) { 48 return dest; 49 } 50 s[3] = s[n - 4] = c; 51 if (n <= 8) { 52 return dest; 53 } 54 55 /* Advance pointer to align it at a 4-byte boundary, 56 * and truncate n to a multiple of 4. The previous code 57 * already took care of any head/tail that get cut off 58 * by the alignment. */ 59 60 k = -(sel4runtime_uintptr_t)s & 3; 61 s += k; 62 n -= k; 63 n &= -4; 64 65#ifdef __GNUC__ 66 typedef sel4runtime_uint32_t __attribute__((__may_alias__)) u32; 67 typedef sel4runtime_uint64_t __attribute__((__may_alias__)) u64; 68 69 u32 c32 = ((u32) - 1) / 255 * (unsigned char)c; 70 71 /* In preparation to copy 32 bytes at a time, aligned on 72 * an 8-byte bounary, fill head/tail up to 28 bytes each. 73 * As in the initial byte-based head/tail fill, each 74 * conditional below ensures that the subsequent offsets 75 * are valid (e.g. !(n<=24) implies n>=28). */ 76 77 *(u32 *)(s + 0) = c32; 78 *(u32 *)(s + n - 4) = c32; 79 if (n <= 8) { 80 return dest; 81 } 82 *(u32 *)(s + 4) = c32; 83 *(u32 *)(s + 8) = c32; 84 *(u32 *)(s + n - 12) = c32; 85 *(u32 *)(s + n - 8) = c32; 86 if (n <= 24) { 87 return dest; 88 } 89 *(u32 *)(s + 12) = c32; 90 *(u32 *)(s + 16) = c32; 91 *(u32 *)(s + 20) = c32; 92 *(u32 *)(s + 24) = c32; 93 *(u32 *)(s + n - 28) = c32; 94 *(u32 *)(s + n - 24) = c32; 95 *(u32 *)(s + n - 20) = c32; 96 *(u32 *)(s + n - 16) = c32; 97 98 /* Align to a multiple of 8 so we can fill 64 bits at a time, 99 * and avoid writing the same bytes twice as much as is 100 * practical without introducing additional branching. */ 101 102 k = 24 + ((sel4runtime_uintptr_t)s & 4); 103 s += k; 104 n -= k; 105 106 /* If this loop is reached, 28 tail bytes have already been 107 * filled, so any remainder when n drops below 32 can be 108 * safely ignored. */ 109 110 u64 c64 = c32 | ((u64)c32 << 32); 111 for (; n >= 32; n -= 32, s += 32) { 112 *(u64 *)(s + 0) = c64; 113 *(u64 *)(s + 8) = c64; 114 *(u64 *)(s + 16) = c64; 115 *(u64 *)(s + 24) = c64; 116 } 117#else 118 /* Pure C fallback with no aliasing violations. */ 119 for (; n; n--, s++) { 120 *s = c; 121 } 122#endif 123 124 return dest; 125} 126