xref: /linux/arch/alpha/lib/tishift.c (revision 742f62b63904cdc20a364a49d2861e32464a0af7)
1*3382beedSMatt Turner // SPDX-License-Identifier: GPL-2.0
2*3382beedSMatt Turner /*
3*3382beedSMatt Turner  * 128-bit shift helpers.
4*3382beedSMatt Turner  *
5*3382beedSMatt Turner  * gcc open-codes a variable 128-bit shift when optimizing for speed, but
6*3382beedSMatt Turner  * calls these libgcc routines when optimizing for size.
7*3382beedSMatt Turner  */
8*3382beedSMatt Turner 
9*3382beedSMatt Turner #include <linux/export.h>
10*3382beedSMatt Turner #include <linux/types.h>
11*3382beedSMatt Turner #include <asm/asm-prototypes.h>
12*3382beedSMatt Turner 
13*3382beedSMatt Turner union ti {
14*3382beedSMatt Turner 	__int128_t val;
15*3382beedSMatt Turner 	struct {
16*3382beedSMatt Turner 		u64 low;
17*3382beedSMatt Turner 		u64 high;
18*3382beedSMatt Turner 	};
19*3382beedSMatt Turner };
20*3382beedSMatt Turner 
__ashlti3(__int128_t a,int shift)21*3382beedSMatt Turner noinstr __int128_t __ashlti3(__int128_t a, int shift)
22*3382beedSMatt Turner {
23*3382beedSMatt Turner 	union ti ti = { .val = a };
24*3382beedSMatt Turner 
25*3382beedSMatt Turner 	if (!shift)
26*3382beedSMatt Turner 		return ti.val;
27*3382beedSMatt Turner 	if (shift < 64) {
28*3382beedSMatt Turner 		ti.high = (ti.high << shift) | (ti.low >> (64 - shift));
29*3382beedSMatt Turner 		ti.low <<= shift;
30*3382beedSMatt Turner 	} else {
31*3382beedSMatt Turner 		ti.high = ti.low << (shift - 64);
32*3382beedSMatt Turner 		ti.low = 0;
33*3382beedSMatt Turner 	}
34*3382beedSMatt Turner 	return ti.val;
35*3382beedSMatt Turner }
36*3382beedSMatt Turner EXPORT_SYMBOL(__ashlti3);
37*3382beedSMatt Turner 
__ashrti3(__int128_t a,int shift)38*3382beedSMatt Turner noinstr __int128_t __ashrti3(__int128_t a, int shift)
39*3382beedSMatt Turner {
40*3382beedSMatt Turner 	union ti ti = { .val = a };
41*3382beedSMatt Turner 
42*3382beedSMatt Turner 	if (!shift)
43*3382beedSMatt Turner 		return ti.val;
44*3382beedSMatt Turner 	if (shift < 64) {
45*3382beedSMatt Turner 		ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
46*3382beedSMatt Turner 		ti.high = (s64)ti.high >> shift;
47*3382beedSMatt Turner 	} else {
48*3382beedSMatt Turner 		ti.low = (s64)ti.high >> (shift - 64);
49*3382beedSMatt Turner 		ti.high = (s64)ti.high >> 63;
50*3382beedSMatt Turner 	}
51*3382beedSMatt Turner 	return ti.val;
52*3382beedSMatt Turner }
53*3382beedSMatt Turner EXPORT_SYMBOL(__ashrti3);
54*3382beedSMatt Turner 
__lshrti3(__int128_t a,int shift)55*3382beedSMatt Turner noinstr __int128_t __lshrti3(__int128_t a, int shift)
56*3382beedSMatt Turner {
57*3382beedSMatt Turner 	union ti ti = { .val = a };
58*3382beedSMatt Turner 
59*3382beedSMatt Turner 	if (!shift)
60*3382beedSMatt Turner 		return ti.val;
61*3382beedSMatt Turner 	if (shift < 64) {
62*3382beedSMatt Turner 		ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
63*3382beedSMatt Turner 		ti.high >>= shift;
64*3382beedSMatt Turner 	} else {
65*3382beedSMatt Turner 		ti.low = ti.high >> (shift - 64);
66*3382beedSMatt Turner 		ti.high = 0;
67*3382beedSMatt Turner 	}
68*3382beedSMatt Turner 	return ti.val;
69*3382beedSMatt Turner }
70*3382beedSMatt Turner EXPORT_SYMBOL(__lshrti3);
71