s390/tishift: Convert __ashlti3(), __ashrti3(), __lshrti3() to C

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>
This commit is contained in:
Heiko Carstens
2026-06-09 12:33:43 +02:00
committed by Alexander Gordeev
parent 661fd726e0
commit 51746fc082
4 changed files with 73 additions and 67 deletions

View 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 */

View File

@@ -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)

64
arch/s390/lib/tishift.c Normal file
View File

@@ -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);

9
arch/s390/lib/tishift.h Normal file
View File

@@ -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 */