Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Simple sanity test of memcpy, memmove, and memset intrinsics. |
| 3 | * (fixed length buffers, variable length buffers, etc.) |
| 4 | */ |
| 5 | |
| 6 | #include <stdint.h> /* cstdint requires -std=c++0x or higher */ |
| 7 | #include <cstdlib> |
| 8 | #include <cstring> |
| 9 | |
| 10 | #include "mem_intrin.h" |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 11 | #include "xdefs.h" |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 12 | |
| 13 | typedef int elem_t; |
| 14 | |
| 15 | /* |
| 16 | * Reset buf to the sequence of bytes: n, n+1, n+2 ... length - 1 |
| 17 | */ |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 18 | static void __attribute__((noinline)) |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 19 | reset_buf(uint8_t *buf, uint8_t init, SizeT length) { |
| 20 | SizeT i; |
| 21 | SizeT v = init; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 22 | for (i = 0; i < length; ++i) |
| 23 | buf[i] = v++; |
| 24 | } |
| 25 | |
| 26 | /* Do a fletcher-16 checksum so that the order of the values matter. |
| 27 | * (Not doing a fletcher-32 checksum, since we are working with |
| 28 | * smaller buffers, whose total won't approach 2**16). |
| 29 | */ |
Jim Stichnoth | dd842db | 2015-01-27 12:53:53 -0800 | [diff] [blame] | 30 | static int __attribute__((noinline)) |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 31 | fletcher_checksum(uint8_t *buf, SizeT length) { |
| 32 | SizeT i; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 33 | int sum = 0; |
| 34 | int sum_of_sums = 0; |
| 35 | const int kModulus = 255; |
| 36 | for (i = 0; i < length; ++i) { |
| 37 | sum = (sum + buf[i]) % kModulus; |
| 38 | sum_of_sums = (sum_of_sums + sum) % kModulus; |
| 39 | } |
| 40 | return (sum_of_sums << 8) | sum; |
| 41 | } |
| 42 | |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 43 | int memcpy_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 44 | reset_buf(buf, init, length); |
Jan Voung | 140bb0d | 2014-07-14 11:51:44 -0700 | [diff] [blame] | 45 | memcpy((void *)buf2, (void *)buf, length); |
| 46 | return fletcher_checksum(buf2, length); |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 47 | } |
| 48 | |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 49 | int memmove_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 50 | int sum1; |
| 51 | int sum2; |
| 52 | const int overlap_bytes = 4 * sizeof(elem_t); |
| 53 | if (length <= overlap_bytes) |
| 54 | return 0; |
| 55 | uint8_t *overlap_buf = buf + overlap_bytes; |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 56 | SizeT reduced_length = length - overlap_bytes; |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 57 | reset_buf(buf, init, length); |
| 58 | |
| 59 | /* Test w/ overlap. */ |
| 60 | memmove((void *)overlap_buf, (void *)buf, reduced_length); |
| 61 | sum1 = fletcher_checksum(overlap_buf, reduced_length); |
| 62 | /* Test w/out overlap. */ |
Jan Voung | 140bb0d | 2014-07-14 11:51:44 -0700 | [diff] [blame] | 63 | memmove((void *)buf2, (void *)buf, length); |
| 64 | sum2 = fletcher_checksum(buf2, length); |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 65 | return sum1 + sum2; |
| 66 | } |
| 67 | |
John Porto | 1d23542 | 2015-08-12 12:37:53 -0700 | [diff] [blame] | 68 | int memset_test(uint8_t *buf, uint8_t *buf2, uint8_t init, SizeT length) { |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 69 | memset((void *)buf, init, length); |
Jan Voung | 140bb0d | 2014-07-14 11:51:44 -0700 | [diff] [blame] | 70 | memset((void *)buf2, init + 4, length); |
| 71 | return fletcher_checksum(buf, length) + fletcher_checksum(buf2, length); |
Jan Voung | 3bd9f1a | 2014-06-18 10:50:57 -0700 | [diff] [blame] | 72 | } |
Andrew Scull | cfa628b | 2015-08-20 14:23:05 -0700 | [diff] [blame] | 73 | |
| 74 | #define X(NBYTES) \ |
| 75 | int memcpy_test_fixed_len_##NBYTES(uint8_t init) { \ |
| 76 | uint8_t buf[NBYTES]; \ |
| 77 | uint8_t buf2[NBYTES]; \ |
| 78 | reset_buf(buf, init, NBYTES); \ |
| 79 | memcpy((void *)buf2, (void *)buf, NBYTES); \ |
| 80 | return fletcher_checksum(buf2, NBYTES); \ |
| 81 | } \ |
| 82 | \ |
| 83 | int memmove_test_fixed_len_##NBYTES(uint8_t init) { \ |
| 84 | uint8_t buf[NBYTES + 16]; \ |
| 85 | uint8_t buf2[NBYTES + 16]; \ |
| 86 | reset_buf(buf, init, NBYTES + 16); \ |
| 87 | reset_buf(buf2, init, NBYTES + 16); \ |
| 88 | /* Move up */ \ |
| 89 | memmove((void *)(buf + 16), (void *)buf, NBYTES); \ |
| 90 | /* Move down */ \ |
| 91 | memmove((void *)buf2, (void *)(buf2 + 16), NBYTES); \ |
| 92 | return fletcher_checksum(buf, NBYTES + 16) + \ |
| 93 | fletcher_checksum(buf2, NBYTES + 16); \ |
| 94 | } \ |
| 95 | \ |
| 96 | int memset_test_fixed_len_##NBYTES(uint8_t init) { \ |
| 97 | uint8_t buf[NBYTES]; \ |
| 98 | memset((void *)buf, init, NBYTES); \ |
| 99 | return fletcher_checksum(buf, NBYTES); \ |
| 100 | } |
| 101 | MEMINTRIN_SIZE_TABLE |
| 102 | #undef X |