memory.h - libzahl - big integer library
 (HTM) git clone git://git.suckless.org/libzahl
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       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 }