2 * Common code for checksum implementations
4 * Copyright (c) 2020, Arm Limited.
5 * SPDX-License-Identifier: MIT
8 #ifndef CHKSUM_COMMON_H
9 #define CHKSUM_COMMON_H
11 #if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__
12 #error Only little endian supported
20 /* Assertions must be explicitly enabled */
24 #define Assert(exp) assert(exp)
26 #define Assert(exp) (void) (exp)
30 #define likely(x) __builtin_expect(!!(x), 1)
31 #define unlikely(x) __builtin_expect(!!(x), 0)
32 #define may_alias __attribute__((__may_alias__))
33 #define always_inline __attribute__((always_inline))
35 #define no_unroll_loops
37 #define no_unroll_loops __attribute__((optimize("no-unroll-loops")))
39 #define bswap16(x) __builtin_bswap16((x))
42 #define unlikely(x) (x)
45 #define no_unroll_loops
46 #define bswap16(x) ((uint8_t)((x) >> 8) | ((uint8_t)(x) << 8))
49 #define ALL_ONES ~UINT64_C(0)
52 uint64_t load64(const void *ptr)
54 /* GCC will optimise this to a normal load instruction */
56 memcpy(&v, ptr, sizeof v);
61 uint32_t load32(const void *ptr)
63 /* GCC will optimise this to a normal load instruction */
65 memcpy(&v, ptr, sizeof v);
70 uint16_t load16(const void *ptr)
72 /* GCC will optimise this to a normal load instruction */
74 memcpy(&v, ptr, sizeof v);
78 /* slurp_small() is for small buffers, don't waste cycles on alignment */
81 static inline uint64_t
82 slurp_small(const void *ptr, uint32_t nbytes)
84 const unsigned char *cptr = ptr;
99 sum += (uint8_t) *cptr;
104 static inline const void *
105 align_ptr(const void *ptr, size_t bytes)
107 return (void *) ((uintptr_t) ptr & -(uintptr_t) bytes);
111 static inline uint16_t
112 fold_and_swap(uint64_t sum, bool swap)
114 /* Fold 64-bit sum to 32 bits */
115 sum = (sum & 0xffffffff) + (sum >> 32);
116 sum = (sum & 0xffffffff) + (sum >> 32);
117 Assert(sum == (uint32_t) sum);
119 /* Fold 32-bit sum to 16 bits */
120 sum = (sum & 0xffff) + (sum >> 16);
121 sum = (sum & 0xffff) + (sum >> 16);
122 Assert(sum == (uint16_t) sum);
124 if (unlikely(swap)) /* Odd base pointer is unexpected */
129 return (uint16_t) sum;