]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/tishift: Convert __ashlti3(), __ashrti3(), __lshrti3() to C
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 9 Jun 2026 10:33:43 +0000 (12:33 +0200)
committerAlexander Gordeev <agordeev@linux.ibm.com>
Wed, 10 Jun 2026 14:55:22 +0000 (16:55 +0200)
There is no reason to have __ashlti3(), __ashrti3(), and __lshrti3()
implemented in assembler. Convert them all to C, which allows the
compiler to optimize the code if newer instructions allow that.

Reviewed-by: Juergen Christ <jchrist@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Gordeev <agordeev@linux.ibm.com>
arch/s390/include/asm/asm-prototypes.h
arch/s390/lib/tishift.S [deleted file]
arch/s390/lib/tishift.c [new file with mode: 0644]
arch/s390/lib/tishift.h [new file with mode: 0644]

index 7bd1801cf241cba151a05cb8cedb60d83d0a0ab0..d4da4436d02beed4c6ca01b3bb7e87e4cac92d14 100644 (file)
@@ -8,8 +8,4 @@
 #include <asm/nospec-branch.h>
 #include <asm-generic/asm-prototypes.h>
 
-__int128_t __ashlti3(__int128_t a, int b);
-__int128_t __ashrti3(__int128_t a, int b);
-__int128_t __lshrti3(__int128_t a, int b);
-
 #endif /* _ASM_S390_PROTOTYPES_H */
diff --git a/arch/s390/lib/tishift.S b/arch/s390/lib/tishift.S
deleted file mode 100644 (file)
index 96214f5..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-
-#include <linux/export.h>
-#include <linux/linkage.h>
-#include <asm/nospec-insn.h>
-
-       .section .noinstr.text, "ax"
-
-       GEN_BR_THUNK %r14
-
-SYM_FUNC_START(__ashlti3)
-       lmg     %r0,%r1,0(%r3)
-       cije    %r4,0,1f
-       lhi     %r3,64
-       sr      %r3,%r4
-       jnh     0f
-       srlg    %r3,%r1,0(%r3)
-       sllg    %r0,%r0,0(%r4)
-       sllg    %r1,%r1,0(%r4)
-       ogr     %r0,%r3
-       j       1f
-0:     sllg    %r0,%r1,-64(%r4)
-       lghi    %r1,0
-1:     stmg    %r0,%r1,0(%r2)
-       BR_EX   %r14
-SYM_FUNC_END(__ashlti3)
-EXPORT_SYMBOL(__ashlti3)
-
-SYM_FUNC_START(__ashrti3)
-       lmg     %r0,%r1,0(%r3)
-       cije    %r4,0,1f
-       lhi     %r3,64
-       sr      %r3,%r4
-       jnh     0f
-       sllg    %r3,%r0,0(%r3)
-       srlg    %r1,%r1,0(%r4)
-       srag    %r0,%r0,0(%r4)
-       ogr     %r1,%r3
-       j       1f
-0:     srag    %r1,%r0,-64(%r4)
-       srag    %r0,%r0,63
-1:     stmg    %r0,%r1,0(%r2)
-       BR_EX   %r14
-SYM_FUNC_END(__ashrti3)
-EXPORT_SYMBOL(__ashrti3)
-
-SYM_FUNC_START(__lshrti3)
-       lmg     %r0,%r1,0(%r3)
-       cije    %r4,0,1f
-       lhi     %r3,64
-       sr      %r3,%r4
-       jnh     0f
-       sllg    %r3,%r0,0(%r3)
-       srlg    %r1,%r1,0(%r4)
-       srlg    %r0,%r0,0(%r4)
-       ogr     %r1,%r3
-       j       1f
-0:     srlg    %r1,%r0,-64(%r4)
-       lghi    %r0,0
-1:     stmg    %r0,%r1,0(%r2)
-       BR_EX   %r14
-SYM_FUNC_END(__lshrti3)
-EXPORT_SYMBOL(__lshrti3)
diff --git a/arch/s390/lib/tishift.c b/arch/s390/lib/tishift.c
new file mode 100644 (file)
index 0000000..bb16cf6
--- /dev/null
@@ -0,0 +1,64 @@
+// 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);
diff --git a/arch/s390/lib/tishift.h b/arch/s390/lib/tishift.h
new file mode 100644 (file)
index 0000000..43a9b8c
--- /dev/null
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _S390_LIB_TISHIFT_H
+#define _S390_LIB_TISHIFT_H
+
+__int128_t __ashlti3(__int128_t a, int b);
+__int128_t __ashrti3(__int128_t a, int b);
+__int128_t __lshrti3(__int128_t a, int b);
+
+#endif /* _S390_LIB_TISHIFT_H */