18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci// Copyright (c) 2019 Facebook 38c2ecf20Sopenharmony_ci#include <features.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_citypedef unsigned int u32; 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_cistatic __always_inline u32 rol32(u32 word, unsigned int shift) 88c2ecf20Sopenharmony_ci{ 98c2ecf20Sopenharmony_ci return (word << shift) | (word >> ((-shift) & 31)); 108c2ecf20Sopenharmony_ci} 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#define __jhash_mix(a, b, c) \ 138c2ecf20Sopenharmony_ci{ \ 148c2ecf20Sopenharmony_ci a -= c; a ^= rol32(c, 4); c += b; \ 158c2ecf20Sopenharmony_ci b -= a; b ^= rol32(a, 6); a += c; \ 168c2ecf20Sopenharmony_ci c -= b; c ^= rol32(b, 8); b += a; \ 178c2ecf20Sopenharmony_ci a -= c; a ^= rol32(c, 16); c += b; \ 188c2ecf20Sopenharmony_ci b -= a; b ^= rol32(a, 19); a += c; \ 198c2ecf20Sopenharmony_ci c -= b; c ^= rol32(b, 4); b += a; \ 208c2ecf20Sopenharmony_ci} 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define __jhash_final(a, b, c) \ 238c2ecf20Sopenharmony_ci{ \ 248c2ecf20Sopenharmony_ci c ^= b; c -= rol32(b, 14); \ 258c2ecf20Sopenharmony_ci a ^= c; a -= rol32(c, 11); \ 268c2ecf20Sopenharmony_ci b ^= a; b -= rol32(a, 25); \ 278c2ecf20Sopenharmony_ci c ^= b; c -= rol32(b, 16); \ 288c2ecf20Sopenharmony_ci a ^= c; a -= rol32(c, 4); \ 298c2ecf20Sopenharmony_ci b ^= a; b -= rol32(a, 14); \ 308c2ecf20Sopenharmony_ci c ^= b; c -= rol32(b, 24); \ 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define JHASH_INITVAL 0xdeadbeef 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_cistatic ATTR 368c2ecf20Sopenharmony_ciu32 jhash(const void *key, u32 length, u32 initval) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci u32 a, b, c; 398c2ecf20Sopenharmony_ci const unsigned char *k = key; 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci a = b = c = JHASH_INITVAL + length + initval; 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci while (length > 12) { 448c2ecf20Sopenharmony_ci a += *(volatile u32 *)(k); 458c2ecf20Sopenharmony_ci b += *(volatile u32 *)(k + 4); 468c2ecf20Sopenharmony_ci c += *(volatile u32 *)(k + 8); 478c2ecf20Sopenharmony_ci __jhash_mix(a, b, c); 488c2ecf20Sopenharmony_ci length -= 12; 498c2ecf20Sopenharmony_ci k += 12; 508c2ecf20Sopenharmony_ci } 518c2ecf20Sopenharmony_ci switch (length) { 528c2ecf20Sopenharmony_ci case 12: c += (u32)k[11]<<24; 538c2ecf20Sopenharmony_ci case 11: c += (u32)k[10]<<16; 548c2ecf20Sopenharmony_ci case 10: c += (u32)k[9]<<8; 558c2ecf20Sopenharmony_ci case 9: c += k[8]; 568c2ecf20Sopenharmony_ci case 8: b += (u32)k[7]<<24; 578c2ecf20Sopenharmony_ci case 7: b += (u32)k[6]<<16; 588c2ecf20Sopenharmony_ci case 6: b += (u32)k[5]<<8; 598c2ecf20Sopenharmony_ci case 5: b += k[4]; 608c2ecf20Sopenharmony_ci case 4: a += (u32)k[3]<<24; 618c2ecf20Sopenharmony_ci case 3: a += (u32)k[2]<<16; 628c2ecf20Sopenharmony_ci case 2: a += (u32)k[1]<<8; 638c2ecf20Sopenharmony_ci case 1: a += k[0]; 648c2ecf20Sopenharmony_ci c ^= a; 658c2ecf20Sopenharmony_ci __jhash_final(a, b, c); 668c2ecf20Sopenharmony_ci case 0: /* Nothing left to add */ 678c2ecf20Sopenharmony_ci break; 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci return c; 718c2ecf20Sopenharmony_ci} 72