DF-5706 / memcchr_fixed_instr.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | /* * Load-instrumented copy of the FIXED memcchr (fix.diff applied to * sys/libkern/memcchr.c). Same instrumentation as memcchr_instr.c. * Expectation: g_below_start == g_past_end == g_outside_granule == 0 * (every load fully in range) while the differential vs the naive * reference stays at zero failures. */ #include "prelude.h" #define LONGPTR_MASK (sizeof(long) - 1) unsigned long g_below_start, g_past_end, g_in; unsigned long g_max_below, g_max_past; unsigned long g_filtered; unsigned long g_outside_granule; const unsigned char *g_lo, *g_hi; #define NOTE(p, sz) do { \ const unsigned char *_p = (const unsigned char *)(p); \ if (_p < g_lo) { \ g_below_start++; \ { unsigned long _d = (unsigned long)(g_lo - _p); \ if (_d > g_max_below) g_max_below = _d; } \ } else if (_p + (sz) > g_hi) { \ g_past_end++; \ { unsigned long _d = (unsigned long)(_p + (sz) - g_hi); \ if (_d > g_max_past) g_max_past = _d; } \ } else g_in++; \ if (_p < (const unsigned char *)((uintptr_t)g_lo & ~(uintptr_t)7) || \ _p + (sz) > \ (const unsigned char *)(((uintptr_t)g_hi + 7) & ~(uintptr_t)7)) \ g_outside_granule++; \ } while (0) #define LDC(e) ({ const unsigned long *_q = (e); \ NOTE((const unsigned char *)_q, sizeof(unsigned long)); *_q; }) #define LDB(e) ({ const unsigned char *_q = (e); NOTE(_q, 1); *_q; }) static int g_c; #define TESTBYTE_I \ do { \ if (LDB(p) != (unsigned char)g_c) \ goto done; \ p++; \ } while (0) void * memcchr_fixed_instr(const void *begin, int c, size_t n) { const unsigned long *lp; const unsigned char *p, *end; unsigned long word; g_c = c; g_lo = (const unsigned char *)begin; g_hi = (const unsigned char *)begin + n; /* Four or eight repetitions of `c'. */ word = (unsigned char)c; word |= word << 8; word |= word << 16; #if LONG_BIT >= 64 word |= word << 32; #endif /* Don't perform memory I/O when passing a zero-length buffer. */ if (n == 0) return (NULL); end = (const unsigned char *)begin + n; /* Compare bytewise until word aligned: no loads below begin. */ for (p = begin; p < end && ((uintptr_t)p & LONGPTR_MASK);) TESTBYTE_I; /* Compare one word at a time while the whole word is in range. */ for (lp = (const unsigned long *)p; (const unsigned char *)(lp + 1) <= end; lp++) { unsigned long w = LDC(lp); if (w != word) { p = (const unsigned char *)lp; TESTBYTE_I; TESTBYTE_I; TESTBYTE_I; #if LONG_BIT >= 64 TESTBYTE_I; TESTBYTE_I; TESTBYTE_I; TESTBYTE_I; #endif goto done; } } /* Trailing bytes: no loads past end. */ for (p = (const unsigned char *)lp; p < end;) TESTBYTE_I; return (NULL); done: if (p >= end) g_filtered++; if (p < end) return (__DECONST(void *, p)); return (NULL); } |