xref: /linux/arch/s390/lib/tishift.c (revision 51746fc082260b0d91fd39315e77cb0863a00136)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #include <linux/export.h>
4 #include <linux/types.h>
5 #include "tishift.h"
6 
7 union ti {
8 	__int128_t val;
9 	struct {
10 		u64 high;
11 		u64 low;
12 	};
13 };
14 
15 noinstr __int128_t __ashlti3(__int128_t a, int shift)
16 {
17 	union ti ti = { .val = a };
18 
19 	if (!shift)
20 		return ti.val;
21 	if (shift < 64) {
22 		ti.high = (ti.high << shift) | (ti.low >> (64 - shift));
23 		ti.low = ti.low << shift;
24 	} else {
25 		ti.high = ti.low << (shift - 64);
26 		ti.low = 0;
27 	}
28 	return ti.val;
29 }
30 EXPORT_SYMBOL(__ashlti3);
31 
32 noinstr __int128_t __ashrti3(__int128_t a, int shift)
33 {
34 	union ti ti = { .val = a };
35 
36 	if (!shift)
37 		return ti.val;
38 	if (shift < 64) {
39 		ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
40 		ti.high = (int64_t)ti.high >> shift;
41 	} else {
42 		ti.low = (int64_t)ti.high >> (shift - 64);
43 		ti.high = (int64_t)ti.high >> 63;
44 	}
45 	return ti.val;
46 }
47 EXPORT_SYMBOL(__ashrti3);
48 
49 noinstr __int128_t __lshrti3(__int128_t a, int shift)
50 {
51 	union ti ti = { .val = a };
52 
53 	if (!shift)
54 		return ti.val;
55 	if (shift < 64) {
56 		ti.low = (ti.low >> shift) | (ti.high << (64 - shift));
57 		ti.high = ti.high >> shift;
58 	} else {
59 		ti.low = ti.high >> (shift - 64);
60 		ti.high = 0;
61 	}
62 	return ti.val;
63 }
64 EXPORT_SYMBOL(__lshrti3);
65