@@ -8,6 +8,11 @@
#include <libcflat.h>
+/* 32-bit ELF base types. */
+typedef u32 Elf32_Addr;
+typedef u32 Elf32_Xword;
+typedef s32 Elf32_Sxword;
+
/* 64-bit ELF base types. */
typedef u64 Elf64_Addr;
typedef u64 Elf64_Xword;
@@ -26,6 +31,12 @@ typedef struct elf64_rel {
Elf64_Xword r_info; /* index and type of relocation */
} Elf64_Rel;
+typedef struct elf32_rela {
+ Elf32_Addr r_offset; /* Location at which to apply the action */
+ Elf32_Xword r_info; /* index and type of relocation */
+ Elf32_Sxword r_addend; /* Constant addend used to compute value */
+} Elf32_Rela;
+
typedef struct elf64_rela {
Elf64_Addr r_offset; /* Location at which to apply the action */
Elf64_Xword r_info; /* index and type of relocation */
@@ -1,5 +1,21 @@
#include <stdint.h>
+#if __riscv_xlen == 32
+int __clzdi2(unsigned long);
+
+int __clzdi2(unsigned long a)
+{
+ int n = 0;
+
+ while (a) {
+ ++n;
+ a >>= 1;
+ }
+
+ return 32 - n;
+}
+#endif
+
extern uint64_t __udivmoddi4(uint64_t num, uint64_t den, uint64_t *p_rem);
extern int64_t __divmoddi4(int64_t num, int64_t den, int64_t *p_rem);
extern int64_t __moddi3(int64_t num, int64_t den);
@@ -1,6 +1,17 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <kbuild.h>
+#include <elf.h>
int main(void)
{
+#if __riscv_xlen == 32
+ OFFSET(ELF_RELA_OFFSET, elf32_rela, r_offset);
+ OFFSET(ELF_RELA_ADDEND, elf32_rela, r_addend);
+ DEFINE(ELF_RELA_SIZE, sizeof(struct elf32_rela));
+#elif __riscv_xlen == 64
+ OFFSET(ELF_RELA_OFFSET, elf64_rela, r_offset);
+ OFFSET(ELF_RELA_ADDEND, elf64_rela, r_addend);
+ DEFINE(ELF_RELA_SIZE, sizeof(struct elf64_rela));
+#endif
return 0;
}
@@ -29,6 +29,9 @@ cflatobjs += lib/riscv/io.o
cflatobjs += lib/riscv/sbi.o
cflatobjs += lib/riscv/setup.o
cflatobjs += lib/riscv/smp.o
+ifeq ($(ARCH),riscv32)
+cflatobjs += lib/ldiv32.o
+endif
########################################
@@ -4,11 +4,23 @@
*
* Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
*/
+#include <asm/asm-offsets.h>
#include <asm/csr.h>
+#if __riscv_xlen == 64
+#define __REG_SEL(a, b) a
+#elif __riscv_xlen == 32
+#define __REG_SEL(a, b) b
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+#define REG_L __REG_SEL(ld, lw)
+#define REG_S __REG_SEL(sd, sw)
+
.macro zero_range, tmp1, tmp2
9998: beq \tmp1, \tmp2, 9997f
- sd zero, 0(\tmp1)
+ REG_S zero, 0(\tmp1)
addi \tmp1, \tmp1, 8
j 9998b
9997:
@@ -33,26 +45,20 @@ start:
/*
* Update all R_RISCV_RELATIVE relocations using the table
- * of Elf64_Rela entries between reloc_start/end. The build
- * will not emit other relocation types.
- *
- * struct Elf64_Rela {
- * uint64_t r_offset;
- * uint64_t r_info;
- * int64_t r_addend;
- * }
+ * of Elf32_Rela/Elf64_Rela entries between reloc_start/end.
+ * The build will not emit other relocation types.
*/
la a1, reloc_start
la a2, reloc_end
la a3, start // base
1:
bge a1, a2, 1f
- ld a4, 0(a1) // r_offset
- ld a5, 16(a1) // r_addend
+ REG_L a4, ELF_RELA_OFFSET(a1) // r_offset
+ REG_L a5, ELF_RELA_ADDEND(a1) // r_addend
add a4, a3, a4 // addr = base + r_offset
add a5, a3, a5 // val = base + r_addend
- sd a5, 0(a4) // *addr = val
- addi a1, a1, 24
+ REG_S a5, 0(a4) // *addr = val
+ addi a1, a1, ELF_RELA_SIZE
j 1b
1:
@@ -72,11 +78,12 @@ start:
/* complete setup */
la a1, stacktop // a1 is the base of free memory
+ mv a2, zero // clear a2 for xlen=32
call setup // a0 is the addr of the dtb
/* run the test */
la a0, __argc
- ld a0, 0(a0)
+ REG_L a0, 0(a0)
la a1, __argv
la a2, __environ
call main
Make a few tweaks to allow also building and running riscv32. Signed-off-by: Andrew Jones <andrew.jones@linux.dev> --- lib/elf.h | 11 +++++++++++ lib/ldiv32.c | 16 ++++++++++++++++ lib/riscv/asm-offsets.c | 11 +++++++++++ riscv/Makefile | 3 +++ riscv/cstart.S | 35 +++++++++++++++++++++-------------- 5 files changed, 62 insertions(+), 14 deletions(-)