1bbbf1280Sopenharmony_ci/* 2bbbf1280Sopenharmony_ci * Common code for checksum implementations 3bbbf1280Sopenharmony_ci * 4bbbf1280Sopenharmony_ci * Copyright (c) 2020, Arm Limited. 5bbbf1280Sopenharmony_ci * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception 6bbbf1280Sopenharmony_ci */ 7bbbf1280Sopenharmony_ci 8bbbf1280Sopenharmony_ci#ifndef CHKSUM_COMMON_H 9bbbf1280Sopenharmony_ci#define CHKSUM_COMMON_H 10bbbf1280Sopenharmony_ci 11bbbf1280Sopenharmony_ci#if __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ 12bbbf1280Sopenharmony_ci#error Only little endian supported 13bbbf1280Sopenharmony_ci#endif 14bbbf1280Sopenharmony_ci 15bbbf1280Sopenharmony_ci#include <limits.h> 16bbbf1280Sopenharmony_ci#include <stdbool.h> 17bbbf1280Sopenharmony_ci#include <stdint.h> 18bbbf1280Sopenharmony_ci#include <string.h> 19bbbf1280Sopenharmony_ci 20bbbf1280Sopenharmony_ci/* Assertions must be explicitly enabled */ 21bbbf1280Sopenharmony_ci#if WANT_ASSERT 22bbbf1280Sopenharmony_ci#undef NDEBUG 23bbbf1280Sopenharmony_ci#include <assert.h> 24bbbf1280Sopenharmony_ci#define Assert(exp) assert(exp) 25bbbf1280Sopenharmony_ci#else 26bbbf1280Sopenharmony_ci#define Assert(exp) (void) (exp) 27bbbf1280Sopenharmony_ci#endif 28bbbf1280Sopenharmony_ci 29bbbf1280Sopenharmony_ci#ifdef __GNUC__ 30bbbf1280Sopenharmony_ci#define likely(x) __builtin_expect(!!(x), 1) 31bbbf1280Sopenharmony_ci#define unlikely(x) __builtin_expect(!!(x), 0) 32bbbf1280Sopenharmony_ci#define may_alias __attribute__((__may_alias__)) 33bbbf1280Sopenharmony_ci#define always_inline __attribute__((always_inline)) 34bbbf1280Sopenharmony_ci#ifdef __clang__ 35bbbf1280Sopenharmony_ci#define no_unroll_loops 36bbbf1280Sopenharmony_ci#else 37bbbf1280Sopenharmony_ci#define no_unroll_loops __attribute__((optimize("no-unroll-loops"))) 38bbbf1280Sopenharmony_ci#endif 39bbbf1280Sopenharmony_ci#define bswap16(x) __builtin_bswap16((x)) 40bbbf1280Sopenharmony_ci#else 41bbbf1280Sopenharmony_ci#define likely(x) (x) 42bbbf1280Sopenharmony_ci#define unlikely(x) (x) 43bbbf1280Sopenharmony_ci#define may_alias 44bbbf1280Sopenharmony_ci#define always_inline 45bbbf1280Sopenharmony_ci#define no_unroll_loops 46bbbf1280Sopenharmony_ci#define bswap16(x) ((uint8_t)((x) >> 8) | ((uint8_t)(x) << 8)) 47bbbf1280Sopenharmony_ci#endif 48bbbf1280Sopenharmony_ci 49bbbf1280Sopenharmony_ci#define ALL_ONES ~UINT64_C(0) 50bbbf1280Sopenharmony_ci 51bbbf1280Sopenharmony_cistatic inline 52bbbf1280Sopenharmony_ciuint64_t load64(const void *ptr) 53bbbf1280Sopenharmony_ci{ 54bbbf1280Sopenharmony_ci /* GCC will optimise this to a normal load instruction */ 55bbbf1280Sopenharmony_ci uint64_t v; 56bbbf1280Sopenharmony_ci memcpy(&v, ptr, sizeof v); 57bbbf1280Sopenharmony_ci return v; 58bbbf1280Sopenharmony_ci} 59bbbf1280Sopenharmony_ci 60bbbf1280Sopenharmony_cistatic inline 61bbbf1280Sopenharmony_ciuint32_t load32(const void *ptr) 62bbbf1280Sopenharmony_ci{ 63bbbf1280Sopenharmony_ci /* GCC will optimise this to a normal load instruction */ 64bbbf1280Sopenharmony_ci uint32_t v; 65bbbf1280Sopenharmony_ci memcpy(&v, ptr, sizeof v); 66bbbf1280Sopenharmony_ci return v; 67bbbf1280Sopenharmony_ci} 68bbbf1280Sopenharmony_ci 69bbbf1280Sopenharmony_cistatic inline 70bbbf1280Sopenharmony_ciuint16_t load16(const void *ptr) 71bbbf1280Sopenharmony_ci{ 72bbbf1280Sopenharmony_ci /* GCC will optimise this to a normal load instruction */ 73bbbf1280Sopenharmony_ci uint16_t v; 74bbbf1280Sopenharmony_ci memcpy(&v, ptr, sizeof v); 75bbbf1280Sopenharmony_ci return v; 76bbbf1280Sopenharmony_ci} 77bbbf1280Sopenharmony_ci 78bbbf1280Sopenharmony_ci/* slurp_small() is for small buffers, don't waste cycles on alignment */ 79bbbf1280Sopenharmony_cino_unroll_loops 80bbbf1280Sopenharmony_cialways_inline 81bbbf1280Sopenharmony_cistatic inline uint64_t 82bbbf1280Sopenharmony_cislurp_small(const void *ptr, uint32_t nbytes) 83bbbf1280Sopenharmony_ci{ 84bbbf1280Sopenharmony_ci const unsigned char *cptr = ptr; 85bbbf1280Sopenharmony_ci uint64_t sum = 0; 86bbbf1280Sopenharmony_ci while (nbytes >= 4) 87bbbf1280Sopenharmony_ci { 88bbbf1280Sopenharmony_ci sum += load32(cptr); 89bbbf1280Sopenharmony_ci cptr += 4; 90bbbf1280Sopenharmony_ci nbytes -= 4; 91bbbf1280Sopenharmony_ci } 92bbbf1280Sopenharmony_ci if (nbytes & 2) 93bbbf1280Sopenharmony_ci { 94bbbf1280Sopenharmony_ci sum += load16(cptr); 95bbbf1280Sopenharmony_ci cptr += 2; 96bbbf1280Sopenharmony_ci } 97bbbf1280Sopenharmony_ci if (nbytes & 1) 98bbbf1280Sopenharmony_ci { 99bbbf1280Sopenharmony_ci sum += (uint8_t) *cptr; 100bbbf1280Sopenharmony_ci } 101bbbf1280Sopenharmony_ci return sum; 102bbbf1280Sopenharmony_ci} 103bbbf1280Sopenharmony_ci 104bbbf1280Sopenharmony_cistatic inline const void * 105bbbf1280Sopenharmony_cialign_ptr(const void *ptr, size_t bytes) 106bbbf1280Sopenharmony_ci{ 107bbbf1280Sopenharmony_ci return (void *) ((uintptr_t) ptr & -(uintptr_t) bytes); 108bbbf1280Sopenharmony_ci} 109bbbf1280Sopenharmony_ci 110bbbf1280Sopenharmony_cialways_inline 111bbbf1280Sopenharmony_cistatic inline uint16_t 112bbbf1280Sopenharmony_cifold_and_swap(uint64_t sum, bool swap) 113bbbf1280Sopenharmony_ci{ 114bbbf1280Sopenharmony_ci /* Fold 64-bit sum to 32 bits */ 115bbbf1280Sopenharmony_ci sum = (sum & 0xffffffff) + (sum >> 32); 116bbbf1280Sopenharmony_ci sum = (sum & 0xffffffff) + (sum >> 32); 117bbbf1280Sopenharmony_ci Assert(sum == (uint32_t) sum); 118bbbf1280Sopenharmony_ci 119bbbf1280Sopenharmony_ci /* Fold 32-bit sum to 16 bits */ 120bbbf1280Sopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 121bbbf1280Sopenharmony_ci sum = (sum & 0xffff) + (sum >> 16); 122bbbf1280Sopenharmony_ci Assert(sum == (uint16_t) sum); 123bbbf1280Sopenharmony_ci 124bbbf1280Sopenharmony_ci if (unlikely(swap)) /* Odd base pointer is unexpected */ 125bbbf1280Sopenharmony_ci { 126bbbf1280Sopenharmony_ci sum = bswap16(sum); 127bbbf1280Sopenharmony_ci } 128bbbf1280Sopenharmony_ci 129bbbf1280Sopenharmony_ci return (uint16_t) sum; 130bbbf1280Sopenharmony_ci} 131bbbf1280Sopenharmony_ci 132bbbf1280Sopenharmony_ci#endif 133