libzahl

big integer library
git clone git://git.suckless.org/libzahl
Log | Files | Refs | README | 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 }