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