| // SPDX-License-Identifier: GPL-2.0 |
| |
| #include <linux/export.h> |
| #include <linux/types.h> |
| #include "tishift.h" |
| |
| union ti { |
| __int128_t val; |
| struct { |
| u64 high; |
| u64 low; |
| }; |
| }; |
| |
| noinstr __int128_t __ashlti3(__int128_t a, int shift) |
| { |
| union ti ti = { .val = a }; |
| |
| if (!shift) |
| return ti.val; |
| if (shift < 64) { |
| ti.high = (ti.high << shift) | (ti.low >> (64 - shift)); |
| ti.low = ti.low << shift; |
| } else { |
| ti.high = ti.low << (shift - 64); |
| ti.low = 0; |
| } |
| return ti.val; |
| } |
| EXPORT_SYMBOL(__ashlti3); |
| |
| noinstr __int128_t __ashrti3(__int128_t a, int shift) |
| { |
| union ti ti = { .val = a }; |
| |
| if (!shift) |
| return ti.val; |
| if (shift < 64) { |
| ti.low = (ti.low >> shift) | (ti.high << (64 - shift)); |
| ti.high = (int64_t)ti.high >> shift; |
| } else { |
| ti.low = (int64_t)ti.high >> (shift - 64); |
| ti.high = (int64_t)ti.high >> 63; |
| } |
| return ti.val; |
| } |
| EXPORT_SYMBOL(__ashrti3); |
| |
| noinstr __int128_t __lshrti3(__int128_t a, int shift) |
| { |
| union ti ti = { .val = a }; |
| |
| if (!shift) |
| return ti.val; |
| if (shift < 64) { |
| ti.low = (ti.low >> shift) | (ti.high << (64 - shift)); |
| ti.high = ti.high >> shift; |
| } else { |
| ti.low = ti.high >> (shift - 64); |
| ti.high = 0; |
| } |
| return ti.val; |
| } |
| EXPORT_SYMBOL(__lshrti3); |