summaryrefslogtreecommitdiff
path: root/arch/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'arch/riscv')
-rw-r--r--arch/riscv/Kconfig3
-rw-r--r--arch/riscv/include/asm/asm-prototypes.h4
-rw-r--r--arch/riscv/kernel/image-vars.h9
-rw-r--r--arch/riscv/lib/Makefile1
-rw-r--r--arch/riscv/lib/ashldi3.S36
-rw-r--r--arch/riscv/lib/ashrdi3.S36
-rw-r--r--arch/riscv/lib/lshrdi3.S36
7 files changed, 122 insertions, 3 deletions
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index 226d3d9fe74e..3f0a647218e4 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -406,9 +406,6 @@ config ARCH_RV32I
bool "RV32I"
depends on NONPORTABLE
select 32BIT
- select GENERIC_LIB_ASHLDI3
- select GENERIC_LIB_ASHRDI3
- select GENERIC_LIB_LSHRDI3
select GENERIC_LIB_UCMPDI2
config ARCH_RV64I
diff --git a/arch/riscv/include/asm/asm-prototypes.h b/arch/riscv/include/asm/asm-prototypes.h
index 5b90ba5314ee..a0ca9efff267 100644
--- a/arch/riscv/include/asm/asm-prototypes.h
+++ b/arch/riscv/include/asm/asm-prototypes.h
@@ -5,6 +5,10 @@
#include <linux/ftrace.h>
#include <asm-generic/asm-prototypes.h>
+long long __lshrdi3(long long a, int b);
+long long __ashrdi3(long long a, int b);
+long long __ashldi3(long long a, int b);
+
long long __lshrti3(long long a, int b);
long long __ashrti3(long long a, int b);
long long __ashlti3(long long a, int b);
diff --git a/arch/riscv/kernel/image-vars.h b/arch/riscv/kernel/image-vars.h
index 3bd9d06a8b8f..7b44b94f1283 100644
--- a/arch/riscv/kernel/image-vars.h
+++ b/arch/riscv/kernel/image-vars.h
@@ -32,6 +32,15 @@ __efistub___init_text_end = __init_text_end;
__efistub_sysfb_primary_display = sysfb_primary_display;
#endif
+/*
+ * These double-word integer shifts are used by the library code, and
+ * the first two of them are required to link EFI stub. Note __ashrdi3()
+ * is not actually used by the stub but this may change in the future.
+ */
+PROVIDE(__efistub___lshrdi3 = __lshrdi3);
+PROVIDE(__efistub___ashldi3 = __ashldi3);
+PROVIDE(__efistub___ashrdi3 = __ashrdi3);
+
#endif
#endif /* __RISCV_KERNEL_IMAGE_VARS_H */
diff --git a/arch/riscv/lib/Makefile b/arch/riscv/lib/Makefile
index 6f767b2a349d..f668b98970bd 100644
--- a/arch/riscv/lib/Makefile
+++ b/arch/riscv/lib/Makefile
@@ -16,6 +16,7 @@ ifeq ($(CONFIG_MMU), y)
lib-$(CONFIG_RISCV_ISA_V) += uaccess_vector.o
endif
lib-$(CONFIG_MMU) += uaccess.o
+lib-$(CONFIG_32BIT) += ashldi3.o ashrdi3.o lshrdi3.o
lib-$(CONFIG_64BIT) += tishift.o
lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
diff --git a/arch/riscv/lib/ashldi3.S b/arch/riscv/lib/ashldi3.S
new file mode 100644
index 000000000000..c3408862e2f6
--- /dev/null
+++ b/arch/riscv/lib/ashldi3.S
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/**
+ * Adopted for the Linux kernel from IPXE project, see
+ * https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+/**
+ * Shift left
+ *
+ * @v a1:a0 Value to shift
+ * @v a2 Shift amount
+ * @ret a1:a0 Shifted value
+ */
+
+SYM_FUNC_START(__ashldi3)
+
+ /* Perform shift by 32 bits, if applicable */
+ li t0, 32
+ sub t1, t0, a2
+ bgtz t1, 1f
+ mv a1, a0
+ mv a0, zero
+1: /* Perform shift by modulo-32 bits, if applicable */
+ andi a2, a2, 0x1f
+ beqz a2, 2f
+ srl t2, a0, t1
+ sll a0, a0, a2
+ sll a1, a1, a2
+ or a1, a1, t2
+2: ret
+
+SYM_FUNC_END(__ashldi3)
+EXPORT_SYMBOL(__ashldi3)
diff --git a/arch/riscv/lib/ashrdi3.S b/arch/riscv/lib/ashrdi3.S
new file mode 100644
index 000000000000..426de0946606
--- /dev/null
+++ b/arch/riscv/lib/ashrdi3.S
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/**
+ * Adopted for the Linux kernel from IPXE project, see
+ * https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+/**
+ * Arithmetic shift right
+ *
+ * @v a1:a0 Value to shift
+ * @v a2 Shift amount
+ * @ret a1:a0 Shifted value
+ */
+
+SYM_FUNC_START(__ashrdi3)
+
+ /* Perform shift by 32 bits, if applicable */
+ li t0, 32
+ sub t1, t0, a2
+ bgtz t1, 1f
+ mv a0, a1
+ srai a1, a1, 31
+1: /* Perform shift by modulo-32 bits, if applicable */
+ andi a2, a2, 0x1f
+ beqz a2, 2f
+ sll t2, a1, t1
+ sra a1, a1, a2
+ srl a0, a0, a2
+ or a0, a0, t2
+2: ret
+
+SYM_FUNC_END(__ashrdi3)
+EXPORT_SYMBOL(__ashrdi3)
diff --git a/arch/riscv/lib/lshrdi3.S b/arch/riscv/lib/lshrdi3.S
new file mode 100644
index 000000000000..1af03985ccb7
--- /dev/null
+++ b/arch/riscv/lib/lshrdi3.S
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/**
+ * Adopted for the Linux kernel from IPXE project, see
+ * https://github.com/ipxe/ipxe/blob/master/src/arch/riscv32/libgcc/llshift.S
+ */
+
+#include <linux/linkage.h>
+#include <asm/asm.h>
+
+/**
+ * Logical shift right
+ *
+ * @v a1:a0 Value to shift
+ * @v a2 Shift amount
+ * @ret a1:a0 Shifted value
+ */
+
+SYM_FUNC_START(__lshrdi3)
+
+ /* Perform shift by 32 bits, if applicable */
+ li t0, 32
+ sub t1, t0, a2
+ bgtz t1, 1f
+ mv a0, a1
+ mv a1, zero
+1: /* Perform shift by modulo-32 bits, if applicable */
+ andi a2, a2, 0x1f
+ beqz a2, 2f
+ sll t2, a1, t1
+ srl a1, a1, a2
+ srl a0, a0, a2
+ or a0, a0, t2
+2: ret
+
+SYM_FUNC_END(__lshrdi3)
+EXPORT_SYMBOL(__lshrdi3)