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_memcpy(void *restrict dest, const void *restrict src, sel4runtime_size_t n) 30{ 31 unsigned char *d = dest; 32 const unsigned char *s = src; 33 34#ifdef __GNUC__ 35 36#if __BYTE_ORDER == __LITTLE_ENDIAN 37#define LS >> 38#define RS << 39#else 40#define LS << 41#define RS >> 42#endif 43 44 typedef sel4runtime_uint32_t __attribute__((__may_alias__)) u32; 45 sel4runtime_uint32_t w, x; 46 47 for (; (sel4runtime_uintptr_t)s % 4 && n; n--) { 48 *d++ = *s++; 49 } 50 51 if ((sel4runtime_uintptr_t)d % 4 == 0) { 52 for (; n >= 16; s += 16, d += 16, n -= 16) { 53 *(u32 *)(d + 0) = *(u32 *)(s + 0); 54 *(u32 *)(d + 4) = *(u32 *)(s + 4); 55 *(u32 *)(d + 8) = *(u32 *)(s + 8); 56 *(u32 *)(d + 12) = *(u32 *)(s + 12); 57 } 58 if (n & 8) { 59 *(u32 *)(d + 0) = *(u32 *)(s + 0); 60 *(u32 *)(d + 4) = *(u32 *)(s + 4); 61 d += 8; 62 s += 8; 63 } 64 if (n & 4) { 65 *(u32 *)(d + 0) = *(u32 *)(s + 0); 66 d += 4; 67 s += 4; 68 } 69 if (n & 2) { 70 *d++ = *s++; 71 *d++ = *s++; 72 } 73 if (n & 1) { 74 *d = *s; 75 } 76 return dest; 77 } 78 79 if (n >= 32) switch ((sel4runtime_uintptr_t)d % 4) { 80 case 1: 81 w = *(u32 *)s; 82 *d++ = *s++; 83 *d++ = *s++; 84 *d++ = *s++; 85 n -= 3; 86 for (; n >= 17; s += 16, d += 16, n -= 16) { 87 x = *(u32 *)(s + 1); 88 *(u32 *)(d + 0) = (w LS 24) | (x RS 8); 89 w = *(u32 *)(s + 5); 90 *(u32 *)(d + 4) = (x LS 24) | (w RS 8); 91 x = *(u32 *)(s + 9); 92 *(u32 *)(d + 8) = (w LS 24) | (x RS 8); 93 w = *(u32 *)(s + 13); 94 *(u32 *)(d + 12) = (x LS 24) | (w RS 8); 95 } 96 break; 97 case 2: 98 w = *(u32 *)s; 99 *d++ = *s++; 100 *d++ = *s++; 101 n -= 2; 102 for (; n >= 18; s += 16, d += 16, n -= 16) { 103 x = *(u32 *)(s + 2); 104 *(u32 *)(d + 0) = (w LS 16) | (x RS 16); 105 w = *(u32 *)(s + 6); 106 *(u32 *)(d + 4) = (x LS 16) | (w RS 16); 107 x = *(u32 *)(s + 10); 108 *(u32 *)(d + 8) = (w LS 16) | (x RS 16); 109 w = *(u32 *)(s + 14); 110 *(u32 *)(d + 12) = (x LS 16) | (w RS 16); 111 } 112 break; 113 case 3: 114 w = *(u32 *)s; 115 *d++ = *s++; 116 n -= 1; 117 for (; n >= 19; s += 16, d += 16, n -= 16) { 118 x = *(u32 *)(s + 3); 119 *(u32 *)(d + 0) = (w LS 8) | (x RS 24); 120 w = *(u32 *)(s + 7); 121 *(u32 *)(d + 4) = (x LS 8) | (w RS 24); 122 x = *(u32 *)(s + 11); 123 *(u32 *)(d + 8) = (w LS 8) | (x RS 24); 124 w = *(u32 *)(s + 15); 125 *(u32 *)(d + 12) = (x LS 8) | (w RS 24); 126 } 127 break; 128 } 129 if (n & 16) { 130 *d++ = *s++; 131 *d++ = *s++; 132 *d++ = *s++; 133 *d++ = *s++; 134 *d++ = *s++; 135 *d++ = *s++; 136 *d++ = *s++; 137 *d++ = *s++; 138 *d++ = *s++; 139 *d++ = *s++; 140 *d++ = *s++; 141 *d++ = *s++; 142 *d++ = *s++; 143 *d++ = *s++; 144 *d++ = *s++; 145 *d++ = *s++; 146 } 147 if (n & 8) { 148 *d++ = *s++; 149 *d++ = *s++; 150 *d++ = *s++; 151 *d++ = *s++; 152 *d++ = *s++; 153 *d++ = *s++; 154 *d++ = *s++; 155 *d++ = *s++; 156 } 157 if (n & 4) { 158 *d++ = *s++; 159 *d++ = *s++; 160 *d++ = *s++; 161 *d++ = *s++; 162 } 163 if (n & 2) { 164 *d++ = *s++; 165 *d++ = *s++; 166 } 167 if (n & 1) { 168 *d = *s; 169 } 170 return dest; 171#endif 172 173 for (; n; n--) { 174 *d++ = *s++; 175 } 176 return dest; 177} 178