| /* | |
| * @TAG(OTHER_MIT) | |
| */ | |
| /* | |
| * Copyright © 2005-2014 Rich Felker, et al. | |
| * | |
| * Permission is hereby granted, free of charge, to any person obtaining | |
| * a copy of this software and associated documentation files (the | |
| * "Software"), to deal in the Software without restriction, including | |
| * without limitation the rights to use, copy, modify, merge, publish, | |
| * distribute, sublicense, and/or sell copies of the Software, and to | |
| * permit persons to whom the Software is furnished to do so, subject to | |
| * the following conditions: | |
| * | |
| * The above copyright notice and this permission notice shall be | |
| * included in all copies or substantial portions of the Software. | |
| * | |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
| * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
| * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. | |
| * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY | |
| * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, | |
| * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE | |
| * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
| */ | |
| #include "util.h" | |
| void *__sel4runtime_memcpy(void *restrict dest, const void *restrict src, sel4runtime_size_t n) | |
| { | |
| unsigned char *d = dest; | |
| const unsigned char *s = src; | |
| #ifdef __GNUC__ | |
| #if __BYTE_ORDER == __LITTLE_ENDIAN | |
| #define LS >> | |
| #define RS << | |
| #else | |
| #define LS << | |
| #define RS >> | |
| #endif | |
| typedef sel4runtime_uint32_t __attribute__((__may_alias__)) u32; | |
| sel4runtime_uint32_t w, x; | |
| for (; (sel4runtime_uintptr_t)s % 4 && n; n--) *d++ = *s++; | |
| if ((sel4runtime_uintptr_t)d % 4 == 0) { | |
| for (; n>=16; s+=16, d+=16, n-=16) { | |
| *(u32 *)(d+0) = *(u32 *)(s+0); | |
| *(u32 *)(d+4) = *(u32 *)(s+4); | |
| *(u32 *)(d+8) = *(u32 *)(s+8); | |
| *(u32 *)(d+12) = *(u32 *)(s+12); | |
| } | |
| if (n&8) { | |
| *(u32 *)(d+0) = *(u32 *)(s+0); | |
| *(u32 *)(d+4) = *(u32 *)(s+4); | |
| d += 8; s += 8; | |
| } | |
| if (n&4) { | |
| *(u32 *)(d+0) = *(u32 *)(s+0); | |
| d += 4; s += 4; | |
| } | |
| if (n&2) { | |
| *d++ = *s++; *d++ = *s++; | |
| } | |
| if (n&1) { | |
| *d = *s; | |
| } | |
| return dest; | |
| } | |
| if (n >= 32) switch ((sel4runtime_uintptr_t)d % 4) { | |
| case 1: | |
| w = *(u32 *)s; | |
| *d++ = *s++; | |
| *d++ = *s++; | |
| *d++ = *s++; | |
| n -= 3; | |
| for (; n>=17; s+=16, d+=16, n-=16) { | |
| x = *(u32 *)(s+1); | |
| *(u32 *)(d+0) = (w LS 24) | (x RS 8); | |
| w = *(u32 *)(s+5); | |
| *(u32 *)(d+4) = (x LS 24) | (w RS 8); | |
| x = *(u32 *)(s+9); | |
| *(u32 *)(d+8) = (w LS 24) | (x RS 8); | |
| w = *(u32 *)(s+13); | |
| *(u32 *)(d+12) = (x LS 24) | (w RS 8); | |
| } | |
| break; | |
| case 2: | |
| w = *(u32 *)s; | |
| *d++ = *s++; | |
| *d++ = *s++; | |
| n -= 2; | |
| for (; n>=18; s+=16, d+=16, n-=16) { | |
| x = *(u32 *)(s+2); | |
| *(u32 *)(d+0) = (w LS 16) | (x RS 16); | |
| w = *(u32 *)(s+6); | |
| *(u32 *)(d+4) = (x LS 16) | (w RS 16); | |
| x = *(u32 *)(s+10); | |
| *(u32 *)(d+8) = (w LS 16) | (x RS 16); | |
| w = *(u32 *)(s+14); | |
| *(u32 *)(d+12) = (x LS 16) | (w RS 16); | |
| } | |
| break; | |
| case 3: | |
| w = *(u32 *)s; | |
| *d++ = *s++; | |
| n -= 1; | |
| for (; n>=19; s+=16, d+=16, n-=16) { | |
| x = *(u32 *)(s+3); | |
| *(u32 *)(d+0) = (w LS 8) | (x RS 24); | |
| w = *(u32 *)(s+7); | |
| *(u32 *)(d+4) = (x LS 8) | (w RS 24); | |
| x = *(u32 *)(s+11); | |
| *(u32 *)(d+8) = (w LS 8) | (x RS 24); | |
| w = *(u32 *)(s+15); | |
| *(u32 *)(d+12) = (x LS 8) | (w RS 24); | |
| } | |
| break; | |
| } | |
| if (n&16) { | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| } | |
| if (n&8) { | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| } | |
| if (n&4) { | |
| *d++ = *s++; *d++ = *s++; *d++ = *s++; *d++ = *s++; | |
| } | |
| if (n&2) { | |
| *d++ = *s++; *d++ = *s++; | |
| } | |
| if (n&1) { | |
| *d = *s; | |
| } | |
| return dest; | |
| #endif | |
| for (; n; n--) *d++ = *s++; | |
| return dest; | |
| } |