memory.h (3488B)
1 /* See LICENSE file for copyright and license details. */ 2 3 #define LIBZAHL_MEM_CASES \ 4 LIBZAHL_X(20); \ 5 LIBZAHL_X(19); \ 6 LIBZAHL_X(18); \ 7 LIBZAHL_X(17); \ 8 LIBZAHL_X(16); \ 9 LIBZAHL_X(15); \ 10 LIBZAHL_X(14); \ 11 LIBZAHL_X(13); \ 12 LIBZAHL_X(12); \ 13 LIBZAHL_X(11); \ 14 LIBZAHL_X(10); \ 15 LIBZAHL_X( 9); \ 16 LIBZAHL_X( 8); \ 17 LIBZAHL_X( 7); \ 18 LIBZAHL_X( 6); \ 19 LIBZAHL_X( 5); \ 20 LIBZAHL_X( 4); \ 21 LIBZAHL_X( 3); \ 22 LIBZAHL_X( 2); \ 23 LIBZAHL_X( 1); \ 24 case 0: break; 25 26 27 #if defined(ZAHL_ISA_MISSING_INDIRECT_JUMP) 28 # define LIBZAHL_SMALL_INPUT_BEGIN(n) 29 # define LIBZAHL_SMALL_INPUT_END 30 #else 31 # define LIBZAHL_SMALL_INPUT_BEGIN(n) switch (n) { LIBZAHL_MEM_CASES default: 32 # define LIBZAHL_SMALL_INPUT_END break; } 33 #endif 34 35 36 ZAHL_INLINE void 37 libzahl_memcpy(register zahl_char_t *restrict d, register const zahl_char_t *restrict s, register size_t n) 38 { 39 #define LIBZAHL_X(I) case I: d[I - 1] = s[I - 1]; 40 LIBZAHL_SMALL_INPUT_BEGIN(n); 41 { 42 #if defined(__x86_64__) && !defined(ZAHL_NO_ASM) 43 /* This crap is needed for clang. */ 44 register zahl_char_t t; 45 __asm__ __volatile__ ( 46 # if defined(ZAHL_ISA_MISSING_INDIRECT_JUMP) 47 "\n testq %[e], %[e]" 48 "\n jz 2f" 49 # endif 50 "\n shlq $3, %[e]" 51 "\n addq %[d], %[e]" 52 "\n 1:" 53 "\n movq 0(%[s]), %[t]" 54 "\n movq %[t], 0(%[d])" 55 "\n movq 8(%[s]), %[t]" 56 "\n movq %[t], 8(%[d])" 57 "\n movq 16(%[s]), %[t]" 58 "\n movq %[t], 16(%[d])" 59 "\n movq 24(%[s]), %[t]" 60 "\n movq %[t], 24(%[d])" 61 "\n addq $32, %[s]" 62 "\n addq $32, %[d]" 63 "\n cmpq %[e], %[d]" 64 "\n jl 1b" 65 # if defined(ZAHL_ISA_MISSING_INDIRECT_JUMP) 66 "\n 2:" 67 # endif 68 : [t]"=r"(t), [d]"+r"(d), [s]"+r"(s), [e]"+r"(n)); 69 #else 70 size_t i; 71 for (i = 0; i < n; i += 4) { 72 d[i + 0] = s[i + 0]; 73 d[i + 1] = s[i + 1]; 74 d[i + 2] = s[i + 2]; 75 d[i + 3] = s[i + 3]; 76 } 77 #endif 78 } 79 LIBZAHL_SMALL_INPUT_END; 80 #undef LIBZAHL_X 81 } 82 83 84 ZAHL_INLINE void 85 libzahl_memset(register zahl_char_t *a, register zahl_char_t v, size_t n) 86 { 87 size_t i; 88 for (i = 0; i < n; i += 4) { 89 a[i + 0] = v; 90 a[i + 1] = v; 91 a[i + 2] = v; 92 a[i + 3] = v; 93 } 94 } 95 96 ZAHL_INLINE void 97 libzahl_memset_precise(register zahl_char_t *a, register zahl_char_t v, size_t n) 98 { 99 size_t i; 100 if (n <= 4) { 101 if (n >= 1) 102 a[0] = v; 103 if (n >= 2) 104 a[1] = v; 105 if (n >= 3) 106 a[2] = v; 107 if (n >= 4) 108 a[3] = v; 109 } else { 110 for (i = 0; (i += 4) <= n;) { 111 a[i - 1] = v; 112 a[i - 2] = v; 113 a[i - 3] = v; 114 a[i - 4] = v; 115 } 116 if (i > n) 117 for (i -= 4; i < n; i++) 118 a[i] = v; 119 } 120 } 121 122 123 ZAHL_INLINE void 124 libzahl_memmovef(register zahl_char_t *d, register const zahl_char_t *s, size_t n) 125 { 126 if (n && n < 4) { 127 d[0] = s[0]; 128 d[1] = s[1]; 129 d[2] = s[2]; 130 } else { 131 size_t i; 132 for (i = 0; i < n; i += 4) { 133 d[i + 0] = s[i + 0]; 134 d[i + 1] = s[i + 1]; 135 d[i + 2] = s[i + 2]; 136 d[i + 3] = s[i + 3]; 137 } 138 } 139 } 140 141 ZAHL_INLINE void 142 libzahl_memmoveb(register zahl_char_t *d, register const zahl_char_t *s, size_t n) 143 { 144 ssize_t i; 145 #define LIBZAHL_X(I) case I: d[I - 1] = s[I - 1]; 146 LIBZAHL_SMALL_INPUT_BEGIN(n); 147 for (i = ((ssize_t)n + 3) & ~3; (i -= 4) >= 0;) { 148 d[i + 3] = s[i + 3]; 149 d[i + 2] = s[i + 2]; 150 d[i + 1] = s[i + 1]; 151 d[i + 0] = s[i + 0]; 152 } 153 LIBZAHL_SMALL_INPUT_END; 154 #undef LIBZAHL_X 155 } 156 157 ZAHL_INLINE void 158 libzahl_memmove(register zahl_char_t *d, register const zahl_char_t *s, size_t n) 159 { 160 if (d < s) 161 libzahl_memmovef(d, s, n); 162 else 163 libzahl_memmoveb(d, s, n); 164 }