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