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 Turnernoinstr __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 Turnernoinstr __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 Turnernoinstr __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