Skip to contentSkip to conversation

Fully support standalone Clang/LLVM toolchains

PATCH New Jessica Clarke 4 participants 24 messages Jul 3, 2021 – Jul 8, 2021 Kbuild

lore
Share & tools
lore
#0 lore raw

cover Fully support standalone Clang/LLVM toolchains

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Jessica Clarke (2):
Makefile: Support building with Clang and LLVM binutils Drop dependency on libgcc by importing part of FreeBSD's libquad

 Makefile                              |  59 ++++--
 lib/utils/libquad/divdi3.c            |  64 ++++++
 lib/utils/libquad/include/limits.h    |  12 ++
 lib/utils/libquad/include/sys/cdefs.h |  12 ++
 lib/utils/libquad/include/sys/types.h |  25 +++
 lib/utils/libquad/moddi3.c            |  66 ++++++
 lib/utils/libquad/objects.mk          |  14 ++
 lib/utils/libquad/qdivrem.c           | 278 ++++++++++++++++++++++++++
 lib/utils/libquad/quad.h              | 105 ++++++++++
 lib/utils/libquad/udivdi3.c           |  52 +++++
 lib/utils/libquad/umoddi3.c           |  54 +++++
 11 files changed, 729 insertions(+), 12 deletions(-)
 create mode 100644 lib/utils/libquad/divdi3.c
 create mode 100644 lib/utils/libquad/include/limits.h
 create mode 100644 lib/utils/libquad/include/sys/cdefs.h
 create mode 100644 lib/utils/libquad/include/sys/types.h
 create mode 100644 lib/utils/libquad/moddi3.c
 create mode 100644 lib/utils/libquad/objects.mk
 create mode 100644 lib/utils/libquad/qdivrem.c
 create mode 100644 lib/utils/libquad/quad.h
 create mode 100644 lib/utils/libquad/udivdi3.c
 create mode 100644 lib/utils/libquad/umoddi3.c
Signature · 1 line
2.31.0
#1 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

---
 Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +47 -12
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC		=	clang
+AR		=	llvm-ar
+LD		=	ld.lld
+OBJCOPY		=	llvm-objcopy
+else
 CC		=	$(CROSS_COMPILE)gcc
-CPP		=	$(CROSS_COMPILE)cpp
 AR		=	$(CROSS_COMPILE)ar
 LD		=	$(CROSS_COMPILE)ld
 OBJCOPY		=	$(CROSS_COMPILE)objcopy
-else
-CC		?=	gcc
-CPP		?=	cpp
-AR		?=	ar
-LD		?=	ld
-OBJCOPY		?=	objcopy
 endif
+CPP		=	$(CC) -E
 AS		=	$(CC)
 DTC		=	dtc
 
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG	=	y
+else
+CC_IS_CLANG	=	n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD	=	y
+else
+LD_IS_LLD	=	n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET	=	-target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)
 OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
 OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
+endif
 
 # Setup platform XLEN
 ifndef PLATFORM_RISCV_XLEN
@@ -194,7 +215,11 @@ else
 endif
 
 # Setup compilation commands flags
-GENFLAGS	=	-I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS	+=	$(CLANG_TARGET)
+GENFLAGS	+=	-Wno-unused-command-line-argument
+endif
+GENFLAGS	+=	-I$(platform_src_dir)/include
 GENFLAGS	+=	-I$(include_dir)
 ifneq ($(OPENSBI_VERSION_GIT),)
 GENFLAGS	+=	-DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""
@@ -208,6 +233,9 @@ CFLAGS		+=	-fno-omit-frame-pointer -fno-optimize-sibling-calls
 CFLAGS		+=	-mno-save-restore -mstrict-align
 CFLAGS		+=	-mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 CFLAGS		+=	-mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)
+CFLAGS		+=	-mno-relax
+endif
 CFLAGS		+=	$(GENFLAGS)
 CFLAGS		+=	$(platform-cflags-y)
 CFLAGS		+=	-fno-pie -no-pie
@@ -222,18 +250,25 @@ ASFLAGS		+=	-fno-omit-frame-pointer -fno-optimize-sibling-calls
 ASFLAGS		+=	-mno-save-restore -mstrict-align
 ASFLAGS		+=	-mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 ASFLAGS		+=	-mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS		+=	-mno-relax
+endif
 ASFLAGS		+=	$(GENFLAGS)
 ASFLAGS		+=	$(platform-asflags-y)
 ASFLAGS		+=	$(firmware-asflags-y)
 
 ARFLAGS		=	rcs
 
-ELFFLAGS	+=	-Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS	+=	-Wl,--build-id=none -Wl,-N -static-libgcc -lgcc
 ELFFLAGS	+=	$(platform-ldflags-y)
 ELFFLAGS	+=	$(firmware-ldflags-y)
 
 MERGEFLAGS	+=	-r
+ifeq ($(LD_IS_LLD),y)
+MERGEFLAGS	+=	-b elf
+else
 MERGEFLAGS	+=	-b elf$(PLATFORM_RISCV_XLEN)-littleriscv
+endif
 MERGEFLAGS	+=	-m elf$(PLATFORM_RISCV_XLEN)lriscv
 
 DTSCPPFLAGS	=	$(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
Signature · 1 line
2.31.0
#2 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Please update the documentation for how to use LLVM to build as well.

Quoted 95 lines
---
 Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +40 -11
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else
 CC             =       $(CROSS_COMPILE)gcc
-CPP            =       $(CROSS_COMPILE)cpp
 AR             =       $(CROSS_COMPILE)ar
 LD             =       $(CROSS_COMPILE)ld
 OBJCOPY                =       $(CROSS_COMPILE)objcopy
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy
 endif
+CPP            =       $(CC) -E
 AS             =       $(CC)
 DTC            =       dtc
 
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)
 OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
 OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
+endif
 
 # Setup platform XLEN
 ifndef PLATFORM_RISCV_XLEN
@@ -194,7 +215,11 @@ else
 endif
 
 # Setup compilation commands flags
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include
 GENFLAGS       +=      -I$(include_dir)
 ifneq ($(OPENSBI_VERSION_GIT),)
 GENFLAGS       +=      -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
 CFLAGS         +=      -mno-save-restore -mstrict-align
 CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
 CFLAGS         +=      $(GENFLAGS)
 CFLAGS         +=      $(platform-cflags-y)
 CFLAGS         +=      -fno-pie -no-pie
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
 ASFLAGS                +=      -mno-save-restore -mstrict-align
 ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 10 lines
Makefile +3 -1
+ASFLAGS                +=      -mno-relax
+endif
 ASFLAGS                +=      $(GENFLAGS)
 ASFLAGS                +=      $(platform-asflags-y)
 ASFLAGS                +=      $(firmware-asflags-y)
 
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls

Quoted 13 lines
Makefile +4 -1
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)
 
 MERGEFLAGS     +=      -r
+ifeq ($(LD_IS_LLD),y)
+MERGEFLAGS     +=      -b elf
+else
 MERGEFLAGS     +=      -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
+endif
 MERGEFLAGS     +=      -m elf$(PLATFORM_RISCV_XLEN)lriscv
 
 DTSCPPFLAGS    =       $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
--

Regards,
Bin

#3 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 118 lines · Bin Meng
Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Please update the documentation for how to use LLVM to build as well.

Quoted 101 lines

---
Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------

1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -1
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else

CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)cpp

AR             =       $(CROSS_COMPILE)ar
LD             =       $(CROSS_COMPILE)ld
OBJCOPY                =       $(CROSS_COMPILE)objcopy
Makefile +0 -6
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy

endif
+CPP = $(CC) -E

AS             =       $(CC)
DTC            =       dtc
Makefile +23 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) +endif

# Setup platform XLEN
ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

endif

# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include

GENFLAGS += -I$(include_dir)
ifneq ($(OPENSBI_VERSION_GIT),)
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS         +=      -mno-save-restore -mstrict-align
CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
CFLAGS         +=      $(GENFLAGS)
CFLAGS         +=      $(platform-cflags-y)
CFLAGS         +=      -fno-pie -no-pie
Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS                +=      -mno-save-restore -mstrict-align
ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
ASFLAGS                +=      $(GENFLAGS)
ASFLAGS                +=      $(platform-asflags-y)
ASFLAGS                +=      $(firmware-asflags-y)
Quoted 6 lines

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 4 lines

ARFLAGS = rcs

Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

No; GCC will forward -N to the linker despite it being a linker-only option, Clang requires it to be manually forwarded with -Wl.

Jess

#4 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 122 lines · Jessica Clarke
Quoted 120 lines · Bin Meng
Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Please update the documentation for how to use LLVM to build as well.

Quoted 103 lines

---
Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------

1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -1
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else

CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)cpp

AR             =       $(CROSS_COMPILE)ar
LD             =       $(CROSS_COMPILE)ld
OBJCOPY                =       $(CROSS_COMPILE)objcopy
Makefile +0 -6
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy

endif
+CPP = $(CC) -E

AS             =       $(CC)
DTC            =       dtc
Makefile +23 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) +endif

# Setup platform XLEN
ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

endif

# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include

GENFLAGS += -I$(include_dir)
ifneq ($(OPENSBI_VERSION_GIT),)
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS         +=      -mno-save-restore -mstrict-align
CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
CFLAGS         +=      $(GENFLAGS)
CFLAGS         +=      $(platform-cflags-y)
CFLAGS         +=      -fno-pie -no-pie
Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS                +=      -mno-save-restore -mstrict-align
ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
ASFLAGS                +=      $(GENFLAGS)
ASFLAGS                +=      $(platform-asflags-y)
ASFLAGS                +=      $(firmware-asflags-y)

ARFLAGS = rcs

Quoted 7 lines
Quoted 4 lines

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 2 lines
Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

No; GCC will forward -N to the linker despite it being a linker-only option, Clang requires it to be manually forwarded with -Wl.

Thanks for the clarification. I suggest we create a separate patch for this change.

Regards,
Bin

#5 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 129 lines · Bin Meng
Quoted 127 lines · Jessica Clarke
Quoted 124 lines · Bin Meng
Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Please update the documentation for how to use LLVM to build as well.

Quoted 103 lines

---
Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------

1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -1
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else

CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)cpp

AR             =       $(CROSS_COMPILE)ar
LD             =       $(CROSS_COMPILE)ld
OBJCOPY                =       $(CROSS_COMPILE)objcopy
Makefile +0 -6
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy

endif
+CPP = $(CC) -E

AS             =       $(CC)
DTC            =       dtc
Makefile +23 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) +endif

# Setup platform XLEN
ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

endif

# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include

GENFLAGS += -I$(include_dir)
ifneq ($(OPENSBI_VERSION_GIT),)
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS         +=      -mno-save-restore -mstrict-align
CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
CFLAGS         +=      $(GENFLAGS)
CFLAGS         +=      $(platform-cflags-y)
CFLAGS         +=      -fno-pie -no-pie
Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS                +=      -mno-save-restore -mstrict-align
ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
ASFLAGS                +=      $(GENFLAGS)
ASFLAGS                +=      $(platform-asflags-y)
ASFLAGS                +=      $(firmware-asflags-y)

ARFLAGS = rcs

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 2 lines
Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

Quoted 5 lines
Quoted 2 lines

No; GCC will forward -N to the linker despite it being a linker-only option, Clang requires it to be manually forwarded with -Wl.

Thanks for the clarification. I suggest we create a separate patch for this change.

That seems like unnecessary busywork. It?s a one-line change that?s needed to support Clang, and not needed when you only support GCC, therefore I don?t see why it should be separate from all the other changes in the same file needed to support Clang/LLVM. I mean, if it?s a requirement to get the patch accepted then I?ll do it, but it seems highly inconsistent and a waste of my time.

Jess

#6 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 137 lines · Jessica Clarke
Quoted 129 lines · Bin Meng
Quoted 127 lines · Jessica Clarke
Quoted 124 lines · Bin Meng
Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Please update the documentation for how to use LLVM to build as well.

Quoted 103 lines

---
Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------

1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -1
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else

CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)cpp

AR             =       $(CROSS_COMPILE)ar
LD             =       $(CROSS_COMPILE)ld
OBJCOPY                =       $(CROSS_COMPILE)objcopy
Makefile +0 -6
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy

endif
+CPP = $(CC) -E

AS             =       $(CC)
DTC            =       dtc
Makefile +23 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) +endif

# Setup platform XLEN
ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

endif

# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include

GENFLAGS += -I$(include_dir)
ifneq ($(OPENSBI_VERSION_GIT),)
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS         +=      -mno-save-restore -mstrict-align
CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
CFLAGS         +=      $(GENFLAGS)
CFLAGS         +=      $(platform-cflags-y)
CFLAGS         +=      -fno-pie -no-pie
Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS                +=      -mno-save-restore -mstrict-align
ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
ASFLAGS                +=      $(GENFLAGS)
ASFLAGS                +=      $(platform-asflags-y)
ASFLAGS                +=      $(firmware-asflags-y)

ARFLAGS = rcs

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 2 lines
Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

Quoted 5 lines
Quoted 2 lines

No; GCC will forward -N to the linker despite it being a linker-only option, Clang requires it to be manually forwarded with -Wl.

Thanks for the clarification. I suggest we create a separate patch for this change.

Quoted 6 lines

That seems like unnecessary busywork. It?s a one-line change that?s needed to support Clang, and not needed when you only support GCC, therefore I don?t see why it should be separate from all the other changes in the same file needed to support Clang/LLVM. I mean, if it?s a requirement to get the patch accepted then I?ll do it, but it seems highly inconsistent and a waste of my time.

Will let Anup to chime in. Or you should document this change in your commit message, to save others' time. Thanks.

Regards,
Bin

#7 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

In reply to Bin Meng
Quoted 15 lines · Bin Meng
Quoted 5 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Quoted 7 lines

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Quoted 1 line

Please update the documentation for how to use LLVM to build as well.

Yes, we will need some documentation about building with LLVM. If you don't want to add it as part of this series then some of us can add it separately.

Quoted 28 lines
Quoted 28 lines
---
 Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -4
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else
 CC             =       $(CROSS_COMPILE)gcc
-CPP            =       $(CROSS_COMPILE)cpp
 AR             =       $(CROSS_COMPILE)ar
 LD             =       $(CROSS_COMPILE)ld
 OBJCOPY                =       $(CROSS_COMPILE)objcopy
-else
-CC             ?=      gcc
Quoted 8 lines

Makefile OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb · line 92

Quoted 8 lines
Makefile +1 -4
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy
 endif
+CPP            =       $(CC) -E
 AS             =       $(CC)
 DTC            =       dtc

There were build issues reported by yocto folks so we had to bring-in "?=" assignments.

How about this ....

ifneq ($(LLVM),)

CC             =       clang
AR             =       llvm-ar
LD             =       ld.lld
OBJCOPY                =       llvm-objcopy
else
CC             ?=       $(CROSS_COMPILE)gcc
AR             ?=       $(CROSS_COMPILE)ar
LD             ?=       $(CROSS_COMPILE)ld

OBJCOPY ?= $(CROSS_COMPILE)objcopy
endif
CPP = $(CC) -E

Quoted 66 lines
Quoted 66 lines
Makefile +35 -3
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)
 OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
 OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
+endif
 
 # Setup platform XLEN
 ifndef PLATFORM_RISCV_XLEN
@@ -194,7 +215,11 @@ else
 endif
 
 # Setup compilation commands flags
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include
 GENFLAGS       +=      -I$(include_dir)
 ifneq ($(OPENSBI_VERSION_GIT),)
 GENFLAGS       +=      -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
 CFLAGS         +=      -mno-save-restore -mstrict-align
 CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
 CFLAGS         +=      $(GENFLAGS)
 CFLAGS         +=      $(platform-cflags-y)
 CFLAGS         +=      -fno-pie -no-pie
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
 ASFLAGS                +=      -mno-save-restore -mstrict-align
 ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
 ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
 ASFLAGS                +=      $(GENFLAGS)
 ASFLAGS                +=      $(platform-asflags-y)
 ASFLAGS                +=      $(firmware-asflags-y)
 
Quoted 6 lines

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 4 lines
Makefile +1 -1
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

I think it makes sense to keep this change here because it is required for clang support and this patch adds clang support.

It will be certainly good to have one sentence in the commit description describing this change. No need to have a separate patch for this change.

Regards,
Anup

Quoted 22 lines
Quoted 4 lines
Makefile +0 -0
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)
 

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls

Quoted 10 lines
Makefile +4 -1
 MERGEFLAGS     +=      -r
+ifeq ($(LD_IS_LLD),y)
+MERGEFLAGS     +=      -b elf
+else
 MERGEFLAGS     +=      -b elf$(PLATFORM_RISCV_XLEN)-littleriscv
+endif
 MERGEFLAGS     +=      -m elf$(PLATFORM_RISCV_XLEN)lriscv
 
 DTSCPPFLAGS    =       $(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp
--

Regards,
Bin

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#8 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 17 lines · Anup Patel
Quoted 15 lines · Bin Meng
Quoted 12 lines · Jessica Clarke

This is intended to mirror the Linux kernel. Building with CC=clang will use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally use = like this now does).

Quoted 4 lines
Quoted 1 line

Please update the documentation for how to use LLVM to build as well.

Yes, we will need some documentation about building with LLVM. If you don't want to add it as part of this series then some of us can add it separately.

I can add some basic documentation in a v2.

Quoted 50 lines
Quoted 27 lines
Quoted 27 lines

---
Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++------------

1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +6 -1
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
 OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
 
 # Setup compilation commands
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else

CC = $(CROSS_COMPILE)gcc
-CPP = $(CROSS_COMPILE)cpp

AR             =       $(CROSS_COMPILE)ar
LD             =       $(CROSS_COMPILE)ld
OBJCOPY                =       $(CROSS_COMPILE)objcopy
Makefile +0 -2
-else
-CC             ?=      gcc
Quoted 8 lines
Quoted 8 lines
Makefile +0 -4
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy

endif
+CPP = $(CC) -E

AS             =       $(CC)
DTC            =       dtc

There were build issues reported by yocto folks so we had to bring-in "?=" assignments.

How about this ....

ifneq ($(LLVM),)

CC             =       clang
AR             =       llvm-ar
LD             =       ld.lld
OBJCOPY                =       llvm-objcopy
else
CC             ?=       $(CROSS_COMPILE)gcc
AR             ?=       $(CROSS_COMPILE)ar
LD             ?=       $(CROSS_COMPILE)ld
Quoted 3 lines

OBJCOPY ?= $(CROSS_COMPILE)objcopy
endif
CPP = $(CC) -E

Well, that then reverts 2e5ede82796960435fff80b27b21dfb399d2e2fb which deliberately stopped using ?= for the non-CROSS_COMPILE case. But the fact that Yocto was seeing build issues makes me think they?re doing something wrong, to be honest. Linux does = not ?= and Yocto can build Linux fine, and it?s always been make CC=foo not CC=foo make as the standard way to override these things. I don?t see anything in opensbi_0.9.bb that messes with these variables; do you have a pointer to reports of the issue? Perhaps whatever was happening several years ago has since been fixed? I can add back the existing code for the non-LLVM case but it?d be nicer to drop it unless someone can demonstrate it?s still needed...

Quoted 72 lines
Quoted 65 lines
Quoted 65 lines
Makefile +23 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine | sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\-arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) +endif

# Setup platform XLEN
ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

endif

# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include

GENFLAGS += -I$(include_dir)
ifneq ($(OPENSBI_VERSION_GIT),)
GENFLAGS += -DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
CFLAGS         +=      -mno-save-restore -mstrict-align
CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
CFLAGS         +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
CFLAGS         +=      $(GENFLAGS)
CFLAGS         +=      $(platform-cflags-y)
CFLAGS         +=      -fno-pie -no-pie
Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-pointer -fno-optimize-sibling-calls
ASFLAGS                +=      -mno-save-restore -mstrict-align
ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -march=$(PLATFORM_RISCV_ISA)
ASFLAGS                +=      -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)
Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
ASFLAGS                +=      $(GENFLAGS)
ASFLAGS                +=      $(platform-asflags-y)
ASFLAGS                +=      $(firmware-asflags-y)
Quoted 6 lines

Makefile ASFLAGS += -fno-omit-frame-pointer -fno-optimize-sibling-calls · line 262

Quoted 4 lines

ARFLAGS = rcs

Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc

This looks like an irrelevant bug fix?

Quoted 5 lines

I think it makes sense to keep this change here because it is required for clang support and this patch adds clang support.

It will be certainly good to have one sentence in the commit description describing this change. No need to have a separate patch for this change.

Sure, will add in v2.

Jess

#9 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

In reply to Jessica Clarke

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 131 lines

This is intended to mirror the Linux kernel. Building with CC=clang will
use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command
line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally
use = like this now does).

---
?Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++---------- --
?1 file changed, 47 insertions(+), 12 deletions(-)

Makefile +0 -0
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define

OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb ?OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git describe 2> /dev/null; fi)
?
?# Setup compilation commands

Makefile +6 -1
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC?????????????=???????clang
+AR?????????????=???????llvm-ar
+LD?????????????=???????ld.lld
+OBJCOPY????????????????=???????llvm-objcopy
+else

?CC?????????????=???????$(CROSS_COMPILE)gcc -CPP????????????=???????$(CROSS_COMPILE)cpp ?AR?????????????=???????$(CROSS_COMPILE)ar ?LD?????????????=???????$(CROSS_COMPILE)ld ?OBJCOPY????????????????=???????$(CROSS_COMPILE)objcopy

Makefile +0 -6
-else
-CC??????????????=??????gcc
-CPP?????????????=??????cpp
-AR??????????????=??????ar
-LD??????????????=??????ld
-OBJCOPY?????????????????=??????objcopy

?endif
+CPP????????????=???????$(CC) -E
?AS?????????????=???????$(CC)
?DTC????????????=???????dtc
?

Makefile +0 -2
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed

's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})

Makefile +20 -0
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG????=???????y
+else
+CC_IS_CLANG????=???????n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD??????=???????y
+else
+LD_IS_LLD??????=???????n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET???=???????-target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine |

sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})

Makefile +3 -0
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)

?OPENSBI_CC_ABI := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\- abi=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP}) ?OPENSBI_CC_ISA := $(shell TMP=$(CC) -v 2>&1 | sed -n 's/.*\(with\- arch=\([a-zA-Z0-9]*\)\).*/\2/p'; echo $${TMP})
+endif
?
?# Setup platform XLEN
?ifndef PLATFORM_RISCV_XLEN

Makefile +0 -0
@@ -194,7 +215,11 @@ else

?endif
?
?# Setup compilation commands flags

Makefile +5 -1
-GENFLAGS???????=???????-I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS???????+=??????$(CLANG_TARGET)
+GENFLAGS???????+=??????-Wno-unused-command-line-argument
+endif
+GENFLAGS???????+=??????-I$(platform_src_dir)/include

?GENFLAGS???????+=??????-I$(include_dir)
?ifneq ($(OPENSBI_VERSION_GIT),)
?GENFLAGS???????+=??????-
DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS??????????????+=??????-fno-omit-frame-

pointer -fno-optimize-sibling-calls ?CFLAGS?????????+=??????-mno-save-restore -mstrict-align ?CFLAGS?????????+=??????-mabi=$(PLATFORM_RISCV_ABI) - march=$(PLATFORM_RISCV_ISA) ?CFLAGS?????????+=??????-mcmodel=$(PLATFORM_RISCV_CODE_MODEL)

Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS?????????+=??????-mno-relax
+endif

?CFLAGS?????????+=??????$(GENFLAGS)
?CFLAGS?????????+=??????$(platform-cflags-y)
?CFLAGS?????????+=??????-fno-pie -no-pie

Makefile +0 -0
@@ -222,18 +250,25 @@ ASFLAGS???????????+=??????-fno-omit-frame-

pointer -fno-optimize-sibling-calls ?ASFLAGS????????????????+=??????-mno-save-restore -mstrict-align ?ASFLAGS????????????????+=??????-mabi=$(PLATFORM_RISCV_ABI) - march=$(PLATFORM_RISCV_ISA) ?ASFLAGS????????????????+=??????-mcmodel=$(PLATFORM_RISCV_CODE_MODEL)

Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS????????????????+=??????-mno-relax
+endif

?ASFLAGS????????????????+=??????$(GENFLAGS) ?ASFLAGS????????????????+=??????$(platform-asflags-y) ?ASFLAGS????????????????+=??????$(firmware-asflags-y) ?
?ARFLAGS????????????????=???????rcs
?

Makefile +1 -1
-ELFFLAGS???????+=??????-Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS???????+=??????-Wl,--build-id=none -Wl,-N -static-libgcc -
Quoted 3 lines

lgcc
?ELFFLAGS???????+=??????$(platform-ldflags-y)
?ELFFLAGS???????+=??????$(firmware-ldflags-y)

I tested it on my computer and clang will use GNU linker by default. Because the GNU linker on my system does not support RISCV, it caused a link error. The following code should be added here:

ifeq ($(LD_IS_LLD),y)
ELFFLAGS += -fuse-ld=lld
endif

Regards,
Xiang W

Quoted 16 lines

?

?MERGEFLAGS?????+=??????-r

Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+MERGEFLAGS?????+=??????-b elf
+else

?MERGEFLAGS?????+=??????-b elf$(PLATFORM_RISCV_XLEN)-littleriscv +endif
?MERGEFLAGS?????+=??????-m elf$(PLATFORM_RISCV_XLEN)lriscv ?
?DTSCPPFLAGS????=???????$(CPPFLAGS) -nostdinc -nostdlib -fno-builtin -D__DTS__ -x assembler-with-cpp

Signature · 1 line
2.31.0
#10 lore raw

PATCH 1/2 Makefile: Support building with Clang and LLVM binutils

Quoted 140 lines · Xiang W

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 132 lines

This is intended to mirror the Linux kernel. Building with CC=clang will
use Clang as the compiler but default to using the existing binutils. Building with LLVM=1 will default to using Clang and LLVM binutils.

Note that the ifdef CROSS_COMPILE is removed, since it served little purpose. Variables assigned with = are still overridable on the command
line, the only difference compared with ?= is whether environment variables also override them, but that's not something Kbuild-using projects usually support (at least Linux and U-Boot both unconditionally
use = like this now does).

---
 Makefile | 59 ++++++++++++++++++++++++++++++++++++++++++++----------
--
 1 file changed, 47 insertions(+), 12 deletions(-)
Makefile +0 -0
index 6b64205..40bcab6 100644
@@ -76,26 +76,47 @@ OPENSBI_VERSION_MINOR=`grep "define

OPENSBI_VERSION_MINOR" $(include_dir)/sbi/sb
OPENSBI_VERSION_GIT=$(shell if [ -d $(src_dir)/.git ]; then git
describe 2> /dev/null; fi)

# Setup compilation commands

Makefile +7 -10
-ifdef CROSS_COMPILE
+ifneq ($(LLVM),)
+CC             =       clang
+AR             =       llvm-ar
+LD             =       ld.lld
+OBJCOPY                =       llvm-objcopy
+else
 CC             =       $(CROSS_COMPILE)gcc
-CPP            =       $(CROSS_COMPILE)cpp
 AR             =       $(CROSS_COMPILE)ar
 LD             =       $(CROSS_COMPILE)ld
 OBJCOPY                =       $(CROSS_COMPILE)objcopy
-else
-CC             ?=      gcc
-CPP            ?=      cpp
-AR             ?=      ar
-LD             ?=      ld
-OBJCOPY                ?=      objcopy
 endif
+CPP            =       $(CC) -E
 AS             =       $(CC)
 DTC            =       dtc
 
-# Guess the compillers xlen
-OPENSBI_CC_XLEN := $(shell TMP=`$(CC) -dumpmachine | sed

's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})

Makefile +20 -0
+ifneq ($(shell $(CC) --version 2>&1 | head -n 1 | grep clang),)
+CC_IS_CLANG    =       y
+else
+CC_IS_CLANG    =       n
+endif
+
+ifneq ($(shell $(LD) --version 2>&1 | head -n 1 | grep LLD),)
+LD_IS_LLD      =       y
+else
+LD_IS_LLD      =       n
+endif
+
+ifeq ($(CC_IS_CLANG),y)
+ifneq ($(CROSS_COMPILE),)
+CLANG_TARGET   =       -target $(notdir $(CROSS_COMPILE:%-=%))
+endif
+endif
+
+# Guess the compiler's XLEN
+OPENSBI_CC_XLEN := $(shell TMP=`$(CC) $(CLANG_TARGET) -dumpmachine |

sed 's/riscv\([0-9][0-9]\).*/\1/'`; echo $${TMP})

Makefile +3 -0
+
+# Guess the compiler's ABI and ISA
+ifneq ($(CC_IS_CLANG),y)
 OPENSBI_CC_ABI := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-

abi=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})
OPENSBI_CC_ISA := $(shell TMP=`$(CC) -v 2>&1 | sed -n 's/.*\(with\-
arch=\([a-zA-Z0-9]*\)\).*/\2/p'`; echo $${TMP})

Makefile +6 -1
+endif
 
 # Setup platform XLEN
 ifndef PLATFORM_RISCV_XLEN
@@ -194,7 +215,11 @@ else
 endif
 
 # Setup compilation commands flags
-GENFLAGS       =       -I$(platform_src_dir)/include
+ifeq ($(CC_IS_CLANG),y)
+GENFLAGS       +=      $(CLANG_TARGET)
+GENFLAGS       +=      -Wno-unused-command-line-argument
+endif
+GENFLAGS       +=      -I$(platform_src_dir)/include
 GENFLAGS       +=      -I$(include_dir)
 ifneq ($(OPENSBI_VERSION_GIT),)
 GENFLAGS       +=      -

DOPENSBI_VERSION_GIT="\"$(OPENSBI_VERSION_GIT)\""

Makefile +0 -0
@@ -208,6 +233,9 @@ CFLAGS              +=      -fno-omit-frame-

pointer -fno-optimize-sibling-calls

 CFLAGS         +=      -mno-save-restore -mstrict-align
 CFLAGS         +=      -mabi=$(PLATFORM_RISCV_ABI) -

march=$(PLATFORM_RISCV_ISA)
CFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)

Makefile +3 -0
+ifeq ($(LD_IS_LLD),y)
+CFLAGS         +=      -mno-relax
+endif
 CFLAGS         +=      $(GENFLAGS)
 CFLAGS         +=      $(platform-cflags-y)
 CFLAGS         +=      -fno-pie -no-pie
@@ -222,18 +250,25 @@ ASFLAGS           +=      -fno-omit-frame-

pointer -fno-optimize-sibling-calls

 ASFLAGS                +=      -mno-save-restore -mstrict-align
 ASFLAGS                +=      -mabi=$(PLATFORM_RISCV_ABI) -

march=$(PLATFORM_RISCV_ISA)
ASFLAGS += -mcmodel=$(PLATFORM_RISCV_CODE_MODEL)

Makefile +4 -1
+ifeq ($(LD_IS_LLD),y)
+ASFLAGS                +=      -mno-relax
+endif
 ASFLAGS                +=      $(GENFLAGS)
 ASFLAGS                +=      $(platform-asflags-y)
 ASFLAGS                +=      $(firmware-asflags-y)
 
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -

lgcc

Quoted 2 lines
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)

I tested it on my computer and clang will use GNU linker by default. Because the GNU linker on my system does not support RISCV, it caused a link error. The following code should be added here:

Quoted 3 lines

ifeq ($(LD_IS_LLD),y)
ELFFLAGS += -fuse-ld=lld
endif

Ah, right, that makes sense, I was testing on FreeBSD where ld is LLD. Will fix in v2.

Jess

#11 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

In reply to Jessica Clarke

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library available; only vendor-provided Clang toolchains specifically for bare metal cross-compiling are likely to provide it.

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

---
 Makefile                              |   2 +-
 lib/utils/libquad/divdi3.c            |  64 ++++++
 lib/utils/libquad/include/limits.h    |  12 ++
 lib/utils/libquad/include/sys/cdefs.h |  12 ++
 lib/utils/libquad/include/sys/types.h |  25 +++
 lib/utils/libquad/moddi3.c            |  66 ++++++
 lib/utils/libquad/objects.mk          |  14 ++
 lib/utils/libquad/qdivrem.c           | 278 ++++++++++++++++++++++++++
 lib/utils/libquad/quad.h              | 105 ++++++++++
 lib/utils/libquad/udivdi3.c           |  52 +++++
 lib/utils/libquad/umoddi3.c           |  54 +++++
 11 files changed, 683 insertions(+), 1 deletion(-)
Makefile +1 -1
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS		+=	$(firmware-asflags-y)
 
 ARFLAGS		=	rcs
 
-ELFFLAGS	+=	-Wl,--build-id=none -Wl,-N -static-libgcc -lgcc
+ELFFLAGS	+=	-Wl,--build-id=none -Wl,-N
 ELFFLAGS	+=	$(platform-ldflags-y)
 ELFFLAGS	+=	$(firmware-ldflags-y)
 
lib/utils/libquad/divdi3.c new file +64 -0

64 lines not on this page · raw message

lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +66 -0

66 lines not on this page · raw message

lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +278 -0

278 lines not on this page · raw message

lib/utils/libquad/quad.h new file +105 -0

105 lines not on this page · raw message

lib/utils/libquad/udivdi3.c new file +52 -0

52 lines not on this page · raw message

lib/utils/libquad/umoddi3.c new file +54 -0

54 lines not on this page · raw message

Signature · 1 line
2.31.0
#12 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

Quoted 8 lines · Jessica Clarke

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library available; only vendor-provided Clang toolchains specifically for bare metal cross-compiling are likely to provide it.

Quoted 4 lines

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

Apart from the query regarding BSD-3-clause compatibility with BSD-2-clause, this looks good to me.

Regards,
Anup

Quoted 777 lines
---
 Makefile                              |   2 +-
 lib/utils/libquad/divdi3.c            |  64 ++++++
 lib/utils/libquad/include/limits.h    |  12 ++
 lib/utils/libquad/include/sys/cdefs.h |  12 ++
 lib/utils/libquad/include/sys/types.h |  25 +++
 lib/utils/libquad/moddi3.c            |  66 ++++++
 lib/utils/libquad/objects.mk          |  14 ++
 lib/utils/libquad/qdivrem.c           | 278 ++++++++++++++++++++++++++
 lib/utils/libquad/quad.h              | 105 ++++++++++
 lib/utils/libquad/udivdi3.c           |  52 +++++
 lib/utils/libquad/umoddi3.c           |  54 +++++
 11 files changed, 683 insertions(+), 1 deletion(-)
Makefile +1 -1
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS             +=      $(firmware-asflags-y)
 
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)
 
lib/utils/libquad/divdi3.c new file +64 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, uq;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b, neg ^= 1;
+       else
+               ub = b;
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +66 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, ur;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b;
+       else
+               ub = b;
+       (void)__qdivrem(ua, ub, &ur);
+       return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +278 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#include "quad.h"
+
+#define        B       (1L << HALF_BITS)       /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+       p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_long qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division algorithm)
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = HHALF(tmp.ul[H]);
+       u[2] = LHALF(tmp.ul[H]);
+       u[3] = HHALF(tmp.ul[L]);
+       u[4] = LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = HHALF(tmp.ul[H]);
+       v[2] = LHALF(tmp.ul[H]);
+       v[3] = HHALF(tmp.ul[L]);
+       v[4] = LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_long rbj;     /* r*B+u[j] (not root boy jim) */
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) / v),
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = u[1] / t;
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = rbj / t;
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and acquiring
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant */
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_long n = COMBINE(uj0, uj1);
+                       qhat = n / v1;
+                       rhat = n % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the loop.
+                * We split this up so that we do not require v[0] = 0,
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is nonzero;
+                * in that (rare) case, qhat was too large (by exactly 1).
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+                               t += u[i + j] + v[i];
+                               u[i + j] = LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = LHALF(u[j] + t);
+               }
+               q[j] = qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (u[i] >> d) |
+                                   LHALF(u[i - 1] << (HALF_BITS - d));
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
lib/utils/libquad/quad.h new file +105 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)quad.h      8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `long'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       quad_t  uq;             /* as an unsigned quad */
+       long    sl[2];          /* as two signed longs */
+       u_long  ul[2];          /* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define        H               _QUAD_HIGHWORD
+#define        L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define        QUAD_BITS       (sizeof(quad_t) * CHAR_BIT)
+#define        LONG_BITS       (sizeof(long) * CHAR_BIT)
+#define        HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define        HHALF(x)        ((x) >> HALF_BITS)
+#define        LHALF(x)        ((x) & ((1L << HALF_BITS) - 1))
+#define        LHUP(x)         ((x) << HALF_BITS)
+
+int            __cmpdi2(quad_t a, quad_t b);
+quad_t         __divdi3(quad_t a, quad_t b);
+quad_t         __moddi3(quad_t a, quad_t b);
+u_quad_t       __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int            __ucmpdi2(u_quad_t a, u_quad_t b);
+u_quad_t       __udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t       __umoddi3(u_quad_t a, u_quad_t b);
+
+typedef unsigned int   qshift_t;
lib/utils/libquad/udivdi3.c new file +52 -0
new file mode 100644
index 0000000..0e6f27e
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)udivdi3.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+
+       return (__qdivrem(a, b, (u_quad_t *)0));
+}
lib/utils/libquad/umoddi3.c new file +54 -1
new file mode 100644
index 0000000..7f45134
@@ -0,0 +1,54 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)umoddi3.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+       u_quad_t r;
+
+       (void)__qdivrem(a, b, &r);
+       return (r);
+}
--

2.31.0

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#13 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

Quoted 10 lines · Anup Patel
Quoted 8 lines · Jessica Clarke

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library available; only vendor-provided Clang toolchains specifically for bare metal cross-compiling are likely to provide it.

Quoted 7 lines
Quoted 4 lines

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

Apart from the query regarding BSD-3-clause compatibility with BSD-2-clause, this looks good to me.

The HTIF and SiFive Test device code is already BSD-3-Clause. It does mean the terms of the 3rd clause (that you can?t use the names of the university nor any other authors of the file to endorse products using the code without their permission) apply to binaries built with the code in it, but that?s already the case given the aforementioned files, and should not be a restriction anyone cares about. Arm?s TF-A is BSD-3-Clause, BBL was BSD-3-Clause, FreeBSD is BSD-3-Clause, it?s hard to find examples of purely BSD-2-Clause software out there as most BSD-licensed software like this has *something* derived from the original BSD sources and thus has the 3rd clause.

Jess

Quoted 782 lines

Regards,
Anup

Quoted 777 lines

---

Makefile                              |   2 +-
lib/utils/libquad/divdi3.c            |  64 ++++++
lib/utils/libquad/include/limits.h    |  12 ++
lib/utils/libquad/include/sys/cdefs.h |  12 ++
lib/utils/libquad/include/sys/types.h |  25 +++
lib/utils/libquad/moddi3.c            |  66 ++++++
lib/utils/libquad/objects.mk          |  14 ++
lib/utils/libquad/qdivrem.c           | 278 ++++++++++++++++++++++++++
lib/utils/libquad/quad.h              | 105 ++++++++++
lib/utils/libquad/udivdi3.c           |  52 +++++
lib/utils/libquad/umoddi3.c           |  54 +++++
11 files changed, 683 insertions(+), 1 deletion(-)
Makefile +0 -0
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS             +=      $(firmware-asflags-y)
 

ARFLAGS = rcs

Makefile +1 -1
-ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -lgcc
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N
ELFFLAGS       +=      $(platform-ldflags-y)
ELFFLAGS       +=      $(firmware-ldflags-y)
lib/utils/libquad/divdi3.c new file +64 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, uq;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b, neg ^= 1;
+       else
+               ub = b;
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +66 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, ur;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b;
+       else
+               ub = b;
+       (void)__qdivrem(ua, ub, &ur);
+       return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +278 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#include "quad.h"
+
+#define        B       (1L << HALF_BITS)       /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+       p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.  As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_long qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division algorithm)
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = HHALF(tmp.ul[H]);
+       u[2] = LHALF(tmp.ul[H]);
+       u[3] = HHALF(tmp.ul[L]);
+       u[4] = LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = HHALF(tmp.ul[H]);
+       v[2] = LHALF(tmp.ul[H]);
+       v[3] = HHALF(tmp.ul[L]);
+       v[4] = LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_long rbj;     /* r*B+u[j] (not root boy jim) */
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) / v),
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = u[1] / t;
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = rbj / t;
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and acquiring
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant */
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_long n = COMBINE(uj0, uj1);
+                       qhat = n / v1;
+                       rhat = n % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the loop.
+                * We split this up so that we do not require v[0] = 0,
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is nonzero;
+                * in that (rare) case, qhat was too large (by exactly 1).
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+                               t += u[i + j] + v[i];
+                               u[i + j] = LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = LHALF(u[j] + t);
+               }
+               q[j] = qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (u[i] >> d) |
+                                   LHALF(u[i - 1] << (HALF_BITS - d));
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
lib/utils/libquad/quad.h new file +105 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)quad.h      8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `long'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       quad_t  uq;             /* as an unsigned quad */
+       long    sl[2];          /* as two signed longs */
+       u_long  ul[2];          /* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define        H               _QUAD_HIGHWORD
+#define        L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define        QUAD_BITS       (sizeof(quad_t) * CHAR_BIT)
+#define        LONG_BITS       (sizeof(long) * CHAR_BIT)
+#define        HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).  (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define        HHALF(x)        ((x) >> HALF_BITS)
+#define        LHALF(x)        ((x) & ((1L << HALF_BITS) - 1))
+#define        LHUP(x)         ((x) << HALF_BITS)
+
+int            __cmpdi2(quad_t a, quad_t b);
+quad_t         __divdi3(quad_t a, quad_t b);
+quad_t         __moddi3(quad_t a, quad_t b);
+u_quad_t       __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int            __ucmpdi2(u_quad_t a, u_quad_t b);
+u_quad_t       __udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t       __umoddi3(u_quad_t a, u_quad_t b);
+
+typedef unsigned int   qshift_t;
lib/utils/libquad/udivdi3.c new file +52 -0
new file mode 100644
index 0000000..0e6f27e
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)udivdi3.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+
+       return (__qdivrem(a, b, (u_quad_t *)0));
+}
lib/utils/libquad/umoddi3.c new file +54 -1
new file mode 100644
index 0000000..7f45134
@@ -0,0 +1,54 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)umoddi3.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+       u_quad_t r;
+
+       (void)__qdivrem(a, b, &r);
+       return (r);
+}
--

2.31.0

--
opensbi mailing list
opensbi at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/opensbi

#14 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

In reply to Jessica Clarke

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 723 lines

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains
bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library
available; only vendor-provided Clang toolchains specifically for bare
metal cross-compiling are likely to provide it.

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

---

?Makefile????????????????????????????? |?? 2 +-
?lib/utils/libquad/divdi3.c??????????? |? 64 ++++++
?lib/utils/libquad/include/limits.h??? |? 12 ++
?lib/utils/libquad/include/sys/cdefs.h |? 12 ++
?lib/utils/libquad/include/sys/types.h |? 25 +++
?lib/utils/libquad/moddi3.c??????????? |? 66 ++++++
?lib/utils/libquad/objects.mk????????? |? 14 ++
?lib/utils/libquad/qdivrem.c?????????? | 278
++++++++++++++++++++++++++
?lib/utils/libquad/quad.h????????????? | 105 ++++++++++
?lib/utils/libquad/udivdi3.c?????????? |? 52 +++++
?lib/utils/libquad/umoddi3.c?????????? |? 54 +++++

?11 files changed, 683 insertions(+), 1 deletion(-)

Makefile +0 -0
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS?????????????+=??????$(firmware-asflags-y)

?
?ARFLAGS????????????????=???????rcs
?
-ELFFLAGS???????+=??????-Wl,--build-id=none -Wl,-N -static-libgcc - lgcc
+ELFFLAGS???????+=??????-Wl,--build-id=none -Wl,-N ?ELFFLAGS???????+=??????$(platform-ldflags-y) ?ELFFLAGS???????+=??????$(firmware-ldflags-y)
?

lib/utils/libquad/divdi3.c new file +5 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/divdi3.c new file +30 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c???8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+???????u_quad_t ua, ub, uq;
+???????int neg;
+
+???????if (a < 0)
+???????????????ua = -(u_quad_t)a, neg = 1;
+???????else
+???????????????ua = a, neg = 0;
+???????if (b < 0)
+???????????????ub = -(u_quad_t)b, neg ^= 1;
+???????else
+???????????????ub = b;
+???????uq = __qdivrem(ua, ub, (u_quad_t *)0);
+???????return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +5 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/moddi3.c new file +32 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c???8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+???????u_quad_t ua, ub, ur;
+???????int neg;
+
+???????if (a < 0)
+???????????????ua = -(u_quad_t)a, neg = 1;
+???????else
+???????????????ua = a, neg = 0;
+???????if (b < 0)
+???????????????ub = -(u_quad_t)b;
+???????else
+???????????????ub = b;
+???????(void)__qdivrem(ua, ub, &ur);
+???????return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +5 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.? This algorithm is from Knuth vol. 2 (2nd

ed),
+ * section 4.3.1, pp. 257--259.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#include "quad.h"
+
+#define????????B???????(1L << HALF_BITS)???????/* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define????????COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they

fit */

lib/utils/libquad/qdivrem.c new file +18 -0
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.? NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+???????int i;
+
+???????for (i = 0; i < len; i++)
+???????????????p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS -

sh));
+???????p[i] = LHALF(p[i] << sh);

lib/utils/libquad/qdivrem.c new file +4 -0
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to

u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.? As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */

lib/utils/libquad/qdivrem.c new file +39 -0
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+???????union uu tmp;
+???????digit *u, *v, *q;
+???????digit v1, v2;
+???????u_long qhat, rhat, t;
+???????int m, n, d, j, i;
+???????digit uspace[5], vspace[5], qspace[5];
+
+???????/*
+??????? * Take care of special cases: divide by zero, and u < v.
+??????? */
+???????if (vq == 0) {
+???????????????/* divide by zero. */
+???????????????static volatile const unsigned int zero = 0;
+
+???????????????tmp.ul[H] = tmp.ul[L] = 1 / zero;
+???????????????if (arq)
+???????????????????????*arq = uq;
+???????????????return (tmp.q);
+???????}
+???????if (uq < vq) {
+???????????????if (arq)
+???????????????????????*arq = uq;
+???????????????return (0);
+???????}
+???????u = &uspace[0];
+???????v = &vspace[0];
+???????q = &qspace[0];
+
+???????/*
+??????? * Break dividend and divisor into digits in base B, then
+??????? * count leading zeros to determine m and n.? When done, we
+??????? * will have:
+??????? *??????u = (u[1]u[2]...u[m+n]) sub B
+??????? *??????v = (v[1]v[2]...v[n]) sub B
+??????? *??????v[1] != 0
+??????? *??????1 < n <= 4 (if n = 1, we use a different division

algorithm)
+??????? *??????m >= 0 (otherwise u < v, which we already checked) +??????? *??????m + n = 4
+??????? * and thus
+??????? *??????m = 4 - n <= 2
+??????? */
+???????tmp.uq = uq;
+???????u[0] = 0;
+???????u[1] = HHALF(tmp.ul[H]);
+???????u[2] = LHALF(tmp.ul[H]);
+???????u[3] = HHALF(tmp.ul[L]);
+???????u[4] = LHALF(tmp.ul[L]);
+???????tmp.uq = vq;
+???????v[1] = HHALF(tmp.ul[H]);
+???????v[2] = LHALF(tmp.ul[H]);
+???????v[3] = HHALF(tmp.ul[L]);
+???????v[4] = LHALF(tmp.ul[L]);
+???????for (n = 4; v[1] == 0; v++) {
+???????????????if (--n == 1) { +???????????????????????u_long rbj;?????/* r*B+u[j] (not root boy jim) */
+???????????????????????digit q1, q2, q3, q4;
+
+???????????????????????/*
+??????????????????????? * Change of plan, per exercise 16. +??????????????????????? *??????r = 0; +??????????????????????? *??????for j = 1..4:
+??????????????????????? *??????????????q[j] = floor((r*B + u[j]) / v),
+??????????????????????? *??????????????r = (r*B + u[j]) % v; +??????????????????????? * We unroll this completely here. +??????????????????????? */
+???????????????????????t = v[2];???????/* nonzero, by definition */ +???????????????????????q1 = u[1] / t; +???????????????????????rbj = COMBINE(u[1] % t, u[2]); +???????????????????????q2 = rbj / t; +???????????????????????rbj = COMBINE(rbj % t, u[3]); +???????????????????????q3 = rbj / t; +???????????????????????rbj = COMBINE(rbj % t, u[4]); +???????????????????????q4 = rbj / t; +???????????????????????if (arq) +???????????????????????????????*arq = rbj % t; +???????????????????????tmp.ul[H] = COMBINE(q1, q2); +???????????????????????tmp.ul[L] = COMBINE(q3, q4); +???????????????????????return (tmp.q);
+???????????????}
+???????}

lib/utils/libquad/qdivrem.c new file +14 -0
+
+???????/*
+??????? * By adjusting q once we determine m, we can guarantee that
+??????? * there is a complete four-digit quotient at &qspace[1] when
+??????? * we finally stop.
+??????? */
+???????for (m = 4 - n; u[1] == 0; u++)
+???????????????m--;
+???????for (i = 4 - m; --i >= 0;)
+???????????????q[i] = 0;
+???????q += 4 - m;
+
+???????/*
+??????? * Here we run Program D, translated from MIX to C and

acquiring
+??????? * a few minor changes.
+??????? *
+??????? * D1: choose multiplier 1 << d to ensure v[1] >= B/2. +??????? */
+???????d = 0;
+???????for (t = v[1]; t < B / 2; t <<= 1) +???????????????d++;
+???????if (d > 0) {
+???????????????shl(&u[0], m + n, d);???????????/* u <<= d */ +???????????????shl(&v[1], n - 1, d);???????????/* v <<= d */ +???????}
+???????/*
+??????? * D2: j = 0.
+??????? */
+???????j = 0;
+???????v1 = v[1];??????/* for D3 -- note that v[1..n] are constant */
+???????v2 = v[2];??????/* for D3 */
+???????do {
+???????????????digit uj0, uj1, uj2;
+
+???????????????/*
+??????????????? * D3: Calculate qhat (\^q, in TeX notation). +??????????????? * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and +??????????????? * let rhat = (u[j]*B + u[j+1]) mod v[1]. +??????????????? * While rhat < B and v[2]*qhat > rhat*B+u[j+2], +??????????????? * decrement qhat and increase rhat correspondingly. +??????????????? * Note that if rhat >= B, v[2]*qhat < rhat*B. +??????????????? */
+???????????????uj0 = u[j + 0];?/* for D3 only -- note that u[j+...] change */
+???????????????uj1 = u[j + 1];?/* for D3 only */ +???????????????uj2 = u[j + 2];?/* for D3 only */ +???????????????if (uj0 == v1) { +???????????????????????qhat = B; +???????????????????????rhat = uj1; +???????????????????????goto qhat_too_big; +???????????????} else {
+???????????????????????u_long n = COMBINE(uj0, uj1); +???????????????????????qhat = n / v1; +???????????????????????rhat = n % v1;
+???????????????}
+???????????????while (v2 * qhat > COMBINE(rhat, uj2)) { +???????qhat_too_big:
+???????????????????????qhat--; +???????????????????????if ((rhat += v1) >= B) +???????????????????????????????break;
+???????????????}
+???????????????/*
+??????????????? * D4: Multiply and subtract. +??????????????? * The variable `t' holds any borrows across the loop.
+??????????????? * We split this up so that we do not require v[0] = 0,
+??????????????? * and to eliminate a final special case. +??????????????? */
+???????????????for (t = 0, i = n; i > 0; i--) { +???????????????????????t = u[i + j] - v[i] * qhat - t; +???????????????????????u[i + j] = LHALF(t); +???????????????????????t = (B - HHALF(t)) & (B - 1); +???????????????}
+???????????????t = u[j] - t;
+???????????????u[j] = LHALF(t);
+???????????????/*
+??????????????? * D5: test remainder.
+??????????????? * There is a borrow if and only if HHALF(t) is nonzero;
+??????????????? * in that (rare) case, qhat was too large (by exactly 1).
+??????????????? * Fix it by adding v[1..n] to u[j..j+n]. +??????????????? */
+???????????????if (HHALF(t)) { +???????????????????????qhat--; +???????????????????????for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+???????????????????????????????t += u[i + j] + v[i]; +???????????????????????????????u[i + j] = LHALF(t); +???????????????????????????????t = HHALF(t); +???????????????????????}
+???????????????????????u[j] = LHALF(u[j] + t); +???????????????}
+???????????????q[j] = qhat;
+???????} while (++j <= m);?????????????/* D7: loop on j. */ +
+???????/*
+??????? * If caller wants the remainder, we have to calculate it as +??????? * u[m..m+n] >> d (this is at most n digits and thus fits in +??????? * u[m+1..m+n], but we may need more source digits). +??????? */
+???????if (arq) {
+???????????????if (d) {
+???????????????????????for (i = m + n; i > m; --i) +???????????????????????????????u[i] = (u[i] >> d) | +?????????????????????????????????? LHALF(u[i - 1] << (HALF_BITS - d));
+???????????????????????u[i] = 0;
+???????????????}
+???????????????tmp.ul[H] = COMBINE(uspace[1], uspace[2]); +???????????????tmp.ul[L] = COMBINE(uspace[3], uspace[4]); +???????????????*arq = tmp.q;
+???????}

lib/utils/libquad/qdivrem.c new file +5 -0
+
+???????tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+???????tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+???????return (tmp.q);
+}
lib/utils/libquad/quad.h new file +5 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *?????@(#)quad.h??????8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */

lib/utils/libquad/quad.h new file +13 -0
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *? - The type long long (aka quad_t) exists.
+ *
+ *? - A quad variable is exactly twice as long as `long'.
+ *
+ *? - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with

128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */

lib/utils/libquad/quad.h new file +6 -0
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka
Quoted 8 lines

quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+???????quad_t??q;??????????????/* as a (signed) quad */ +???????quad_t??uq;?????????????/* as an unsigned quad */ +???????long????sl[2];??????????/* as two signed longs */ +???????u_long??ul[2];??????????/* as two unsigned longs */

The length of the long one is different under RV32 and RV64, here you should want to use the 32bit type, it is recommended to use int

Regards,
Xiang W

Quoted 208 lines
lib/utils/libquad/quad.h new file +10 -0
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define????????H???????????????_QUAD_HIGHWORD
+#define????????L???????????????_QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it

up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */

lib/utils/libquad/quad.h new file +6 -0
+#define????????QUAD_BITS???????(sizeof(quad_t) * CHAR_BIT)
+#define????????LONG_BITS???????(sizeof(long) * CHAR_BIT)
+#define????????HALF_BITS???????(sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low

shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).? (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */

lib/utils/libquad/quad.h new file +13 -0
+#define????????HHALF(x)????????((x) >> HALF_BITS)
+#define????????LHALF(x)????????((x) & ((1L << HALF_BITS) - 1))
+#define????????LHUP(x)?????????((x) << HALF_BITS)
+
+int????????????__cmpdi2(quad_t a, quad_t b);
+quad_t?????????__divdi3(quad_t a, quad_t b);
+quad_t?????????__moddi3(quad_t a, quad_t b);
+u_quad_t???????__qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int????????????__ucmpdi2(u_quad_t a, u_quad_t b);
+u_quad_t???????__udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t???????__umoddi3(u_quad_t a, u_quad_t b);
+
+typedef unsigned int???qshift_t;
lib/utils/libquad/udivdi3.c new file +5 -0
new file mode 100644
index 0000000..0e6f27e
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/udivdi3.c new file +18 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)udivdi3.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+
+???????return (__qdivrem(a, b, (u_quad_t *)0));
+}
lib/utils/libquad/umoddi3.c new file +5 -0
new file mode 100644
index 0000000..7f45134
@@ -0,0 +1,54 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/umoddi3.c new file +20 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)umoddi3.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+???????u_quad_t r;
+
+???????(void)__qdivrem(a, b, &r);
+???????return (r);
+}
Signature · 1 line
2.31.0
#15 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

Jess

Quoted 728 lines · Xiang W

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 725 lines

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains
bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library
available; only vendor-provided Clang toolchains specifically for bare
metal cross-compiling are likely to provide it.

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

---
 Makefile                              |   2 +-
 lib/utils/libquad/divdi3.c            |  64 ++++++
 lib/utils/libquad/include/limits.h    |  12 ++
 lib/utils/libquad/include/sys/cdefs.h |  12 ++
 lib/utils/libquad/include/sys/types.h |  25 +++
 lib/utils/libquad/moddi3.c            |  66 ++++++
 lib/utils/libquad/objects.mk          |  14 ++
 lib/utils/libquad/qdivrem.c           | 278
++++++++++++++++++++++++++
 lib/utils/libquad/quad.h              | 105 ++++++++++
 lib/utils/libquad/udivdi3.c           |  52 +++++
 lib/utils/libquad/umoddi3.c           |  54 +++++
 11 files changed, 683 insertions(+), 1 deletion(-)
Makefile +0 -1
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS             +=      $(firmware-asflags-y)
 
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -

lgcc

Makefile +1 -0
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)
lib/utils/libquad/divdi3.c new file +5 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/divdi3.c new file +30 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, uq;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b, neg ^= 1;
+       else
+               ub = b;
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +5 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/moddi3.c new file +32 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, ur;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b;
+       else
+               ub = b;
+       (void)__qdivrem(ua, ub, &ur);
+       return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +5 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd

ed),
+ * section 4.3.1, pp. 257--259.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#include "quad.h"
+
+#define        B       (1L << HALF_BITS)       /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they

fit */

lib/utils/libquad/qdivrem.c new file +18 -0
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS -

sh));

lib/utils/libquad/qdivrem.c new file +5 -0
+       p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to

u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long. As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */

lib/utils/libquad/qdivrem.c new file +39 -0
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_long qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division

algorithm)

lib/utils/libquad/qdivrem.c new file +19 -0
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = HHALF(tmp.ul[H]);
+       u[2] = LHALF(tmp.ul[H]);
+       u[3] = HHALF(tmp.ul[L]);
+       u[4] = LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = HHALF(tmp.ul[H]);
+       v[2] = LHALF(tmp.ul[H]);
+       v[3] = HHALF(tmp.ul[L]);
+       v[4] = LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_long rbj;     /* r*B+u[j] (not root boy

jim) */

lib/utils/libquad/qdivrem.c new file +7 -0
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) /

v),

lib/utils/libquad/qdivrem.c new file +32 -0
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = u[1] / t;
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = rbj / t;
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and

acquiring

lib/utils/libquad/qdivrem.c new file +16 -0
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant

*/

lib/utils/libquad/qdivrem.c new file +13 -0
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...]

change */

lib/utils/libquad/qdivrem.c new file +20 -0
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_long n = COMBINE(uj0, uj1);
+                       qhat = n / v1;
+                       rhat = n % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the

loop.
+ * We split this up so that we do not require v[0] =
0,

lib/utils/libquad/qdivrem.c new file +12 -0
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is

nonzero;
+ * in that (rare) case, qhat was too large (by
exactly 1).

lib/utils/libquad/qdivrem.c new file +5 -0
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add

back. */

lib/utils/libquad/qdivrem.c new file +19 -0
+                               t += u[i + j] + v[i];
+                               u[i + j] = LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = LHALF(u[j] + t);
+               }
+               q[j] = qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (u[i] >> d) |
+                                   LHALF(u[i - 1] << (HALF_BITS -

d));

lib/utils/libquad/qdivrem.c new file +11 -0
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
lib/utils/libquad/quad.h new file +5 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)quad.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */

lib/utils/libquad/quad.h new file +13 -0
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `long'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with

128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */

lib/utils/libquad/quad.h new file +6 -0
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka

quad_t) in
+ * one or more of the following formats.

Quoted 8 lines

lib/utils/libquad/quad.h line 66

Quoted 6 lines

+ */

lib/utils/libquad/quad.h new file +5 -0
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       quad_t  uq;             /* as an unsigned quad */
+       long    sl[2];          /* as two signed longs */
+       u_long  ul[2];          /* as two unsigned longs */

The length of the long one is different under RV32 and RV64, here you should want to use the 32bit type, it is recommended to use int

1. These files are only built on RV32 so that?s irrelevant.
2. This is what the upstream source uses.
3. On RV64 you would not implement 64-bit arithmetic with a pair of ints.
4. The implementation is deliberately designed to be 2*sizeof(long) so it can be reused for 128-bit arithmetic on 64-bit processors if you really want (though the function names would need to change), as you can see in the comment at the top of the file.

Jess

#16 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

In reply to Jessica Clarke

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 764 lines

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains
bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library
available; only vendor-provided Clang toolchains specifically for bare
metal cross-compiling are likely to provide it.

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

---

?Makefile????????????????????????????? |?? 2 +-
?lib/utils/libquad/divdi3.c??????????? |? 64 ++++++
?lib/utils/libquad/include/limits.h??? |? 12 ++
?lib/utils/libquad/include/sys/cdefs.h |? 12 ++
?lib/utils/libquad/include/sys/types.h |? 25 +++
?lib/utils/libquad/moddi3.c??????????? |? 66 ++++++
?lib/utils/libquad/objects.mk????????? |? 14 ++
?lib/utils/libquad/qdivrem.c?????????? | 278
++++++++++++++++++++++++++
?lib/utils/libquad/quad.h????????????? | 105 ++++++++++
?lib/utils/libquad/udivdi3.c?????????? |? 52 +++++
?lib/utils/libquad/umoddi3.c?????????? |? 54 +++++

?11 files changed, 683 insertions(+), 1 deletion(-)

Makefile +0 -0
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS?????????????+=??????$(firmware-asflags-y)

?
?ARFLAGS????????????????=???????rcs
?
-ELFFLAGS???????+=??????-Wl,--build-id=none -Wl,-N -static-libgcc - lgcc
+ELFFLAGS???????+=??????-Wl,--build-id=none -Wl,-N ?ELFFLAGS???????+=??????$(platform-ldflags-y) ?ELFFLAGS???????+=??????$(firmware-ldflags-y)
?

lib/utils/libquad/divdi3.c new file +5 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/divdi3.c new file +30 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c???8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+???????u_quad_t ua, ub, uq;
+???????int neg;
+
+???????if (a < 0)
+???????????????ua = -(u_quad_t)a, neg = 1;
+???????else
+???????????????ua = a, neg = 0;
+???????if (b < 0)
+???????????????ub = -(u_quad_t)b, neg ^= 1;
+???????else
+???????????????ub = b;
+???????uq = __qdivrem(ua, ub, (u_quad_t *)0);
+???????return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +5 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/moddi3.c new file +32 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c???8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+???????u_quad_t ua, ub, ur;
+???????int neg;
+
+???????if (a < 0)
+???????????????ua = -(u_quad_t)a, neg = 1;
+???????else
+???????????????ua = a, neg = 0;
+???????if (b < 0)
+???????????????ub = -(u_quad_t)b;
+???????else
+???????????????ub = b;
+???????(void)__qdivrem(ua, ub, &ur);
+???????return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +5 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.? This algorithm is from Knuth vol. 2 (2nd

ed),
+ * section 4.3.1, pp. 257--259.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#include "quad.h"
+
+#define????????B???????(1L << HALF_BITS)???????/* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define????????COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they

fit */

lib/utils/libquad/qdivrem.c new file +18 -0
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.? NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+???????int i;
+
+???????for (i = 0; i < len; i++)
+???????????????p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS -

sh));
+???????p[i] = LHALF(p[i] << sh);

lib/utils/libquad/qdivrem.c new file +4 -0
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to

u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long.? As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */

lib/utils/libquad/qdivrem.c new file +39 -0
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+???????union uu tmp;
+???????digit *u, *v, *q;
+???????digit v1, v2;
+???????u_long qhat, rhat, t;
+???????int m, n, d, j, i;
+???????digit uspace[5], vspace[5], qspace[5];
+
+???????/*
+??????? * Take care of special cases: divide by zero, and u < v.
+??????? */
+???????if (vq == 0) {
+???????????????/* divide by zero. */
+???????????????static volatile const unsigned int zero = 0;
+
+???????????????tmp.ul[H] = tmp.ul[L] = 1 / zero;
+???????????????if (arq)
+???????????????????????*arq = uq;
+???????????????return (tmp.q);
+???????}
+???????if (uq < vq) {
+???????????????if (arq)
+???????????????????????*arq = uq;
+???????????????return (0);
+???????}
+???????u = &uspace[0];
+???????v = &vspace[0];
+???????q = &qspace[0];
+
+???????/*
+??????? * Break dividend and divisor into digits in base B, then
+??????? * count leading zeros to determine m and n.? When done, we
+??????? * will have:
+??????? *??????u = (u[1]u[2]...u[m+n]) sub B
+??????? *??????v = (v[1]v[2]...v[n]) sub B
+??????? *??????v[1] != 0
+??????? *??????1 < n <= 4 (if n = 1, we use a different division

algorithm)
+??????? *??????m >= 0 (otherwise u < v, which we already checked) +??????? *??????m + n = 4
+??????? * and thus
+??????? *??????m = 4 - n <= 2
+??????? */
+???????tmp.uq = uq;
+???????u[0] = 0;
+???????u[1] = HHALF(tmp.ul[H]);
+???????u[2] = LHALF(tmp.ul[H]);
+???????u[3] = HHALF(tmp.ul[L]);
+???????u[4] = LHALF(tmp.ul[L]);
+???????tmp.uq = vq;
+???????v[1] = HHALF(tmp.ul[H]);
+???????v[2] = LHALF(tmp.ul[H]);
+???????v[3] = HHALF(tmp.ul[L]);
+???????v[4] = LHALF(tmp.ul[L]);
+???????for (n = 4; v[1] == 0; v++) {
+???????????????if (--n == 1) { +???????????????????????u_long rbj;?????/* r*B+u[j] (not root boy jim) */
+???????????????????????digit q1, q2, q3, q4;
+
+???????????????????????/*
+??????????????????????? * Change of plan, per exercise 16. +??????????????????????? *??????r = 0; +??????????????????????? *??????for j = 1..4:
+??????????????????????? *??????????????q[j] = floor((r*B + u[j]) / v),
+??????????????????????? *??????????????r = (r*B + u[j]) % v; +??????????????????????? * We unroll this completely here. +??????????????????????? */
+???????????????????????t = v[2];???????/* nonzero, by definition */ +???????????????????????q1 = u[1] / t; +???????????????????????rbj = COMBINE(u[1] % t, u[2]); +???????????????????????q2 = rbj / t; +???????????????????????rbj = COMBINE(rbj % t, u[3]); +???????????????????????q3 = rbj / t; +???????????????????????rbj = COMBINE(rbj % t, u[4]); +???????????????????????q4 = rbj / t; +???????????????????????if (arq) +???????????????????????????????*arq = rbj % t; +???????????????????????tmp.ul[H] = COMBINE(q1, q2); +???????????????????????tmp.ul[L] = COMBINE(q3, q4); +???????????????????????return (tmp.q);
+???????????????}
+???????}

lib/utils/libquad/qdivrem.c new file +14 -0
+
+???????/*
+??????? * By adjusting q once we determine m, we can guarantee that
+??????? * there is a complete four-digit quotient at &qspace[1] when
+??????? * we finally stop.
+??????? */
+???????for (m = 4 - n; u[1] == 0; u++)
+???????????????m--;
+???????for (i = 4 - m; --i >= 0;)
+???????????????q[i] = 0;
+???????q += 4 - m;
+
+???????/*
+??????? * Here we run Program D, translated from MIX to C and

acquiring
+??????? * a few minor changes.
+??????? *
+??????? * D1: choose multiplier 1 << d to ensure v[1] >= B/2. +??????? */
+???????d = 0;
+???????for (t = v[1]; t < B / 2; t <<= 1) +???????????????d++;
+???????if (d > 0) {
+???????????????shl(&u[0], m + n, d);???????????/* u <<= d */ +???????????????shl(&v[1], n - 1, d);???????????/* v <<= d */ +???????}
+???????/*
+??????? * D2: j = 0.
+??????? */
+???????j = 0;
+???????v1 = v[1];??????/* for D3 -- note that v[1..n] are constant */
+???????v2 = v[2];??????/* for D3 */
+???????do {
+???????????????digit uj0, uj1, uj2;
+
+???????????????/*
+??????????????? * D3: Calculate qhat (\^q, in TeX notation). +??????????????? * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and +??????????????? * let rhat = (u[j]*B + u[j+1]) mod v[1]. +??????????????? * While rhat < B and v[2]*qhat > rhat*B+u[j+2], +??????????????? * decrement qhat and increase rhat correspondingly. +??????????????? * Note that if rhat >= B, v[2]*qhat < rhat*B. +??????????????? */
+???????????????uj0 = u[j + 0];?/* for D3 only -- note that u[j+...] change */
+???????????????uj1 = u[j + 1];?/* for D3 only */ +???????????????uj2 = u[j + 2];?/* for D3 only */ +???????????????if (uj0 == v1) { +???????????????????????qhat = B; +???????????????????????rhat = uj1; +???????????????????????goto qhat_too_big; +???????????????} else {
+???????????????????????u_long n = COMBINE(uj0, uj1); +???????????????????????qhat = n / v1; +???????????????????????rhat = n % v1;
+???????????????}
+???????????????while (v2 * qhat > COMBINE(rhat, uj2)) { +???????qhat_too_big:
+???????????????????????qhat--; +???????????????????????if ((rhat += v1) >= B) +???????????????????????????????break;
+???????????????}
+???????????????/*
+??????????????? * D4: Multiply and subtract. +??????????????? * The variable `t' holds any borrows across the loop.
+??????????????? * We split this up so that we do not require v[0] = 0,
+??????????????? * and to eliminate a final special case. +??????????????? */
+???????????????for (t = 0, i = n; i > 0; i--) { +???????????????????????t = u[i + j] - v[i] * qhat - t; +???????????????????????u[i + j] = LHALF(t); +???????????????????????t = (B - HHALF(t)) & (B - 1); +???????????????}
+???????????????t = u[j] - t;
+???????????????u[j] = LHALF(t);
+???????????????/*
+??????????????? * D5: test remainder.
+??????????????? * There is a borrow if and only if HHALF(t) is nonzero;
+??????????????? * in that (rare) case, qhat was too large (by exactly 1).
+??????????????? * Fix it by adding v[1..n] to u[j..j+n]. +??????????????? */
+???????????????if (HHALF(t)) { +???????????????????????qhat--; +???????????????????????for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+???????????????????????????????t += u[i + j] + v[i]; +???????????????????????????????u[i + j] = LHALF(t); +???????????????????????????????t = HHALF(t); +???????????????????????}
+???????????????????????u[j] = LHALF(u[j] + t); +???????????????}
+???????????????q[j] = qhat;
+???????} while (++j <= m);?????????????/* D7: loop on j. */ +
+???????/*
+??????? * If caller wants the remainder, we have to calculate it as +??????? * u[m..m+n] >> d (this is at most n digits and thus fits in +??????? * u[m+1..m+n], but we may need more source digits). +??????? */
+???????if (arq) {
+???????????????if (d) {
+???????????????????????for (i = m + n; i > m; --i) +???????????????????????????????u[i] = (u[i] >> d) | +?????????????????????????????????? LHALF(u[i - 1] << (HALF_BITS - d));
+???????????????????????u[i] = 0;
+???????????????}
+???????????????tmp.ul[H] = COMBINE(uspace[1], uspace[2]); +???????????????tmp.ul[L] = COMBINE(uspace[3], uspace[4]); +???????????????*arq = tmp.q;
+???????}

lib/utils/libquad/qdivrem.c new file +5 -0
+
+???????tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+???????tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+???????return (tmp.q);
+}
lib/utils/libquad/quad.h new file +5 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *?????@(#)quad.h??????8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */

lib/utils/libquad/quad.h new file +13 -0
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *? - The type long long (aka quad_t) exists.
+ *
+ *? - A quad variable is exactly twice as long as `long'.
+ *
+ *? - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with

128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */

lib/utils/libquad/quad.h new file +6 -0
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka

quad_t) in
+ * one or more of the following formats.
+ */

lib/utils/libquad/quad.h new file +15 -0
+union uu {
+???????quad_t??q;??????????????/* as a (signed) quad */
+???????quad_t??uq;?????????????/* as an unsigned quad */
+???????long????sl[2];??????????/* as two signed longs */
+???????u_long??ul[2];??????????/* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define????????H???????????????_QUAD_HIGHWORD
+#define????????L???????????????_QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it

up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */

lib/utils/libquad/quad.h new file +6 -0
+#define????????QUAD_BITS???????(sizeof(quad_t) * CHAR_BIT)
+#define????????LONG_BITS???????(sizeof(long) * CHAR_BIT)
+#define????????HALF_BITS???????(sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low

shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)).? (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */

lib/utils/libquad/quad.h

Quoted 5 lines
lib/utils/libquad/quad.h new file +5 -0
+#define????????HHALF(x)????????((x) >> HALF_BITS)
+#define????????LHALF(x)????????((x) & ((1L << HALF_BITS) - 1))
+#define????????LHUP(x)?????????((x) << HALF_BITS)
+
+int????????????__cmpdi2(quad_t a, quad_t b);

Is this function used to compare two 64-bit variables? I tested the comparison operation with gcc/clang, and the comparison operation does not call any functions. And this function is not defined, this declaration can be removed.

lib/utils/libquad/quad.h

Quoted 4 lines
lib/utils/libquad/quad.h new file +4 -0
+quad_t?????????__divdi3(quad_t a, quad_t b);
+quad_t?????????__moddi3(quad_t a, quad_t b);
+u_quad_t???????__qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int????????????__ucmpdi2(u_quad_t a, u_quad_t b);

Here the same as above.

Regards,
Xiang W

Quoted 166 lines
lib/utils/libquad/quad.h new file +4 -0
+u_quad_t???????__udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t???????__umoddi3(u_quad_t a, u_quad_t b);
+
+typedef unsigned int???qshift_t;
lib/utils/libquad/udivdi3.c new file +5 -0
new file mode 100644
index 0000000..0e6f27e
@@ -0,0 +1,52 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/udivdi3.c new file +18 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)udivdi3.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(u_quad_t a, u_quad_t b)
+{
+
+???????return (__qdivrem(a, b, (u_quad_t *)0));
+}
lib/utils/libquad/umoddi3.c new file +5 -0
new file mode 100644
index 0000000..7f45134
@@ -0,0 +1,54 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *?????The Regents of the University of California.? All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *??? notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *??? notice, this list of conditions and the following disclaimer in the
+ *??? documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *??? may be used to endorse or promote products derived from this software
+ *??? without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.? IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/umoddi3.c new file +20 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)umoddi3.c??8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(u_quad_t a, u_quad_t b)
+{
+???????u_quad_t r;
+
+???????(void)__qdivrem(a, b, &r);
+???????return (r);
+}
Signature · 1 line
2.31.0
#17 lore raw

PATCH 2/2 Drop dependency on libgcc by importing part of FreeBSD's libquad

Quoted 777 lines · Xiang W

? 2021-07-03???? 18:56 +0100?Jessica Clarke???

Quoted 764 lines

We only need libgcc for 64-bit division on RV32. Whilst GCC toolchains
bundle libgcc, Clang toolchains tend not to ship libclang_rt.builtins given every compiler is a cross-compiler for every target and so you would need a silly number of builds of it, with only the native library
available; only vendor-provided Clang toolchains specifically for bare
metal cross-compiling are likely to provide it.

Thus, import part of FreeBSD's implementation of the division support functions needed and stop linking against libgcc.

---
 Makefile                              |   2 +-
 lib/utils/libquad/divdi3.c            |  64 ++++++
 lib/utils/libquad/include/limits.h    |  12 ++
 lib/utils/libquad/include/sys/cdefs.h |  12 ++
 lib/utils/libquad/include/sys/types.h |  25 +++
 lib/utils/libquad/moddi3.c            |  66 ++++++
 lib/utils/libquad/objects.mk          |  14 ++
 lib/utils/libquad/qdivrem.c           | 278
++++++++++++++++++++++++++
 lib/utils/libquad/quad.h              | 105 ++++++++++
 lib/utils/libquad/udivdi3.c           |  52 +++++
 lib/utils/libquad/umoddi3.c           |  54 +++++
 11 files changed, 683 insertions(+), 1 deletion(-)
Makefile +0 -1
index 40bcab6..bc4429a 100644
@@ -259,7 +259,7 @@ ASFLAGS             +=      $(firmware-asflags-y)
 
 ARFLAGS                =       rcs
 
-ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N -static-libgcc -

lgcc

Makefile +1 -0
+ELFFLAGS       +=      -Wl,--build-id=none -Wl,-N
 ELFFLAGS       +=      $(platform-ldflags-y)
 ELFFLAGS       +=      $(firmware-ldflags-y)
lib/utils/libquad/divdi3.c new file +5 -0
new file mode 100644
index 0000000..c5b4a37
@@ -0,0 +1,64 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/divdi3.c new file +30 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, uq;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b, neg ^= 1;
+       else
+               ub = b;
+       uq = __qdivrem(ua, ub, (u_quad_t *)0);
+       return (neg ? -uq : uq);
+}
lib/utils/libquad/include/limits.h new file +12 -0
new file mode 100644
index 0000000..9c69d27
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __LIMITS_H__
+#define __LIMITS_H__
+
+#define CHAR_BIT 8
+
+#endif
lib/utils/libquad/include/sys/cdefs.h new file +12 -0
new file mode 100644
index 0000000..e8d6faa
@@ -0,0 +1,12 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_CDEFS_H__
+#define __SYS_CDEFS_H__
+
+#define __FBSDID(s) struct __hack
+
+#endif
lib/utils/libquad/include/sys/types.h new file +25 -0
new file mode 100644
index 0000000..e372437
@@ -0,0 +1,25 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Jessica Clarke <[email protected]>
+ */
+
+#ifndef __SYS_TYPES_H__
+#define __SYS_TYPES_H__
+
+#include <sbi/sbi_types.h>
+
+typedef unsigned long u_long;
+
+typedef int64_t quad_t;
+typedef uint64_t u_quad_t;
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define _QUAD_LOWWORD 1
+#define _QUAD_HIGHWORD 0
+#else
+#define _QUAD_LOWWORD 0
+#define _QUAD_HIGHWORD 1
+#endif
+
+#endif
lib/utils/libquad/moddi3.c new file +5 -0
new file mode 100644
index 0000000..fc13b4d
@@ -0,0 +1,66 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/moddi3.c new file +32 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c   8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(quad_t a, quad_t b)
+{
+       u_quad_t ua, ub, ur;
+       int neg;
+
+       if (a < 0)
+               ua = -(u_quad_t)a, neg = 1;
+       else
+               ua = a, neg = 0;
+       if (b < 0)
+               ub = -(u_quad_t)b;
+       else
+               ub = b;
+       (void)__qdivrem(ua, ub, &ur);
+       return (neg ? -ur : ur);
+}
lib/utils/libquad/objects.mk new file +14 -0
new file mode 100644
index 0000000..5e53cd0
@@ -0,0 +1,14 @@
+#
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2021 Jessica Clarke <[email protected]>
+#
+
+ifeq ($(PLATFORM_RISCV_XLEN),32)
+libsbiutils-objs-y += libquad/divdi3.o
+libsbiutils-objs-y += libquad/moddi3.o
+libsbiutils-objs-y += libquad/qdivrem.o
+libsbiutils-objs-y += libquad/udivdi3.o
+libsbiutils-objs-y += libquad/umoddi3.o
+libsbiutils-genflags-y += -I$(libsbiutils_dir)/libquad/include
+endif
lib/utils/libquad/qdivrem.c new file +5 -0
new file mode 100644
index 0000000..ea09e7f
@@ -0,0 +1,278 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c  8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide.  This algorithm is from Knuth vol. 2 (2nd

ed),
+ * section 4.3.1, pp. 257--259.
+ */

lib/utils/libquad/qdivrem.c new file +9 -0
+
+#include "quad.h"
+
+#define        B       (1L << HALF_BITS)       /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define        COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they

fit */

lib/utils/libquad/qdivrem.c new file +18 -0
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0.  NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+       int i;
+
+       for (i = 0; i < len; i++)
+               p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS -

sh));

lib/utils/libquad/qdivrem.c new file +5 -0
+       p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to

u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long. As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */

lib/utils/libquad/qdivrem.c new file +39 -0
+u_quad_t
+__qdivrem(u_quad_t uq, u_quad_t vq, u_quad_t *arq)
+{
+       union uu tmp;
+       digit *u, *v, *q;
+       digit v1, v2;
+       u_long qhat, rhat, t;
+       int m, n, d, j, i;
+       digit uspace[5], vspace[5], qspace[5];
+
+       /*
+        * Take care of special cases: divide by zero, and u < v.
+        */
+       if (vq == 0) {
+               /* divide by zero. */
+               static volatile const unsigned int zero = 0;
+
+               tmp.ul[H] = tmp.ul[L] = 1 / zero;
+               if (arq)
+                       *arq = uq;
+               return (tmp.q);
+       }
+       if (uq < vq) {
+               if (arq)
+                       *arq = uq;
+               return (0);
+       }
+       u = &uspace[0];
+       v = &vspace[0];
+       q = &qspace[0];
+
+       /*
+        * Break dividend and divisor into digits in base B, then
+        * count leading zeros to determine m and n.  When done, we
+        * will have:
+        *      u = (u[1]u[2]...u[m+n]) sub B
+        *      v = (v[1]v[2]...v[n]) sub B
+        *      v[1] != 0
+        *      1 < n <= 4 (if n = 1, we use a different division

algorithm)

lib/utils/libquad/qdivrem.c new file +19 -0
+        *      m >= 0 (otherwise u < v, which we already checked)
+        *      m + n = 4
+        * and thus
+        *      m = 4 - n <= 2
+        */
+       tmp.uq = uq;
+       u[0] = 0;
+       u[1] = HHALF(tmp.ul[H]);
+       u[2] = LHALF(tmp.ul[H]);
+       u[3] = HHALF(tmp.ul[L]);
+       u[4] = LHALF(tmp.ul[L]);
+       tmp.uq = vq;
+       v[1] = HHALF(tmp.ul[H]);
+       v[2] = LHALF(tmp.ul[H]);
+       v[3] = HHALF(tmp.ul[L]);
+       v[4] = LHALF(tmp.ul[L]);
+       for (n = 4; v[1] == 0; v++) {
+               if (--n == 1) {
+                       u_long rbj;     /* r*B+u[j] (not root boy

jim) */

lib/utils/libquad/qdivrem.c new file +7 -0
+                       digit q1, q2, q3, q4;
+
+                       /*
+                        * Change of plan, per exercise 16.
+                        *      r = 0;
+                        *      for j = 1..4:
+                        *              q[j] = floor((r*B + u[j]) /

v),

lib/utils/libquad/qdivrem.c new file +32 -0
+                        *              r = (r*B + u[j]) % v;
+                        * We unroll this completely here.
+                        */
+                       t = v[2];       /* nonzero, by definition */
+                       q1 = u[1] / t;
+                       rbj = COMBINE(u[1] % t, u[2]);
+                       q2 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[3]);
+                       q3 = rbj / t;
+                       rbj = COMBINE(rbj % t, u[4]);
+                       q4 = rbj / t;
+                       if (arq)
+                               *arq = rbj % t;
+                       tmp.ul[H] = COMBINE(q1, q2);
+                       tmp.ul[L] = COMBINE(q3, q4);
+                       return (tmp.q);
+               }
+       }
+
+       /*
+        * By adjusting q once we determine m, we can guarantee that
+        * there is a complete four-digit quotient at &qspace[1] when
+        * we finally stop.
+        */
+       for (m = 4 - n; u[1] == 0; u++)
+               m--;
+       for (i = 4 - m; --i >= 0;)
+               q[i] = 0;
+       q += 4 - m;
+
+       /*
+        * Here we run Program D, translated from MIX to C and

acquiring

lib/utils/libquad/qdivrem.c new file +16 -0
+        * a few minor changes.
+        *
+        * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+        */
+       d = 0;
+       for (t = v[1]; t < B / 2; t <<= 1)
+               d++;
+       if (d > 0) {
+               shl(&u[0], m + n, d);           /* u <<= d */
+               shl(&v[1], n - 1, d);           /* v <<= d */
+       }
+       /*
+        * D2: j = 0.
+        */
+       j = 0;
+       v1 = v[1];      /* for D3 -- note that v[1..n] are constant

*/

lib/utils/libquad/qdivrem.c new file +13 -0
+       v2 = v[2];      /* for D3 */
+       do {
+               digit uj0, uj1, uj2;
+
+               /*
+                * D3: Calculate qhat (\^q, in TeX notation).
+                * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+                * let rhat = (u[j]*B + u[j+1]) mod v[1].
+                * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+                * decrement qhat and increase rhat correspondingly.
+                * Note that if rhat >= B, v[2]*qhat < rhat*B.
+                */
+               uj0 = u[j + 0]; /* for D3 only -- note that u[j+...]

change */

lib/utils/libquad/qdivrem.c new file +20 -0
+               uj1 = u[j + 1]; /* for D3 only */
+               uj2 = u[j + 2]; /* for D3 only */
+               if (uj0 == v1) {
+                       qhat = B;
+                       rhat = uj1;
+                       goto qhat_too_big;
+               } else {
+                       u_long n = COMBINE(uj0, uj1);
+                       qhat = n / v1;
+                       rhat = n % v1;
+               }
+               while (v2 * qhat > COMBINE(rhat, uj2)) {
+       qhat_too_big:
+                       qhat--;
+                       if ((rhat += v1) >= B)
+                               break;
+               }
+               /*
+                * D4: Multiply and subtract.
+                * The variable `t' holds any borrows across the

loop.
+ * We split this up so that we do not require v[0] =
0,

lib/utils/libquad/qdivrem.c new file +12 -0
+                * and to eliminate a final special case.
+                */
+               for (t = 0, i = n; i > 0; i--) {
+                       t = u[i + j] - v[i] * qhat - t;
+                       u[i + j] = LHALF(t);
+                       t = (B - HHALF(t)) & (B - 1);
+               }
+               t = u[j] - t;
+               u[j] = LHALF(t);
+               /*
+                * D5: test remainder.
+                * There is a borrow if and only if HHALF(t) is

nonzero;
+ * in that (rare) case, qhat was too large (by
exactly 1).

lib/utils/libquad/qdivrem.c new file +5 -0
+                * Fix it by adding v[1..n] to u[j..j+n].
+                */
+               if (HHALF(t)) {
+                       qhat--;
+                       for (t = 0, i = n; i > 0; i--) { /* D6: add

back. */

lib/utils/libquad/qdivrem.c new file +19 -0
+                               t += u[i + j] + v[i];
+                               u[i + j] = LHALF(t);
+                               t = HHALF(t);
+                       }
+                       u[j] = LHALF(u[j] + t);
+               }
+               q[j] = qhat;
+       } while (++j <= m);             /* D7: loop on j. */
+
+       /*
+        * If caller wants the remainder, we have to calculate it as
+        * u[m..m+n] >> d (this is at most n digits and thus fits in
+        * u[m+1..m+n], but we may need more source digits).
+        */
+       if (arq) {
+               if (d) {
+                       for (i = m + n; i > m; --i)
+                               u[i] = (u[i] >> d) |
+                                   LHALF(u[i - 1] << (HALF_BITS -

d));

lib/utils/libquad/qdivrem.c new file +11 -0
+                       u[i] = 0;
+               }
+               tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+               tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+               *arq = tmp.q;
+       }
+
+       tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+       tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+       return (tmp.q);
+}
lib/utils/libquad/quad.h new file +5 -0
new file mode 100644
index 0000000..a9f8447
@@ -0,0 +1,105 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights

reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
in the
+ * documentation and/or other materials provided with the
distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this
software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)quad.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */

lib/utils/libquad/quad.h new file +13 -0
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ *  - The type long long (aka quad_t) exists.
+ *
+ *  - A quad variable is exactly twice as long as `long'.
+ *
+ *  - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with

128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */

lib/utils/libquad/quad.h new file +6 -0
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka

quad_t) in
+ * one or more of the following formats.
+ */

lib/utils/libquad/quad.h new file +15 -0
+union uu {
+       quad_t  q;              /* as a (signed) quad */
+       quad_t  uq;             /* as an unsigned quad */
+       long    sl[2];          /* as two signed longs */
+       u_long  ul[2];          /* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define        H               _QUAD_HIGHWORD
+#define        L               _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it

up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */

lib/utils/libquad/quad.h new file +6 -0
+#define        QUAD_BITS       (sizeof(quad_t) * CHAR_BIT)
+#define        LONG_BITS       (sizeof(long) * CHAR_BIT)
+#define        HALF_BITS       (sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low

shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */

lib/utils/libquad/quad.h line 97

Quoted 5 lines
lib/utils/libquad/quad.h new file +5 -0
+#define        HHALF(x)        ((x) >> HALF_BITS)
+#define        LHALF(x)        ((x) & ((1L << HALF_BITS) - 1))
+#define        LHUP(x)         ((x) << HALF_BITS)
+
+int            __cmpdi2(quad_t a, quad_t b);

Is this function used to compare two 64-bit variables? I tested the comparison operation with gcc/clang, and the comparison operation does not call any functions. And this function is not defined, this declaration can be removed.

Quoted 6 lines

lib/utils/libquad/quad.h line 101

Quoted 4 lines
lib/utils/libquad/quad.h new file +4 -0
+quad_t         __divdi3(quad_t a, quad_t b);
+quad_t         __moddi3(quad_t a, quad_t b);
+u_quad_t       __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int            __ucmpdi2(u_quad_t a, u_quad_t b);

Here the same as above.

They do no harm to have, the headers are only included by the files inside libquad themselves, they?re not used by opensbi itself. Removing them would require modifying the source compared with upstream, which makes it more awkward to pull in newer versions. I have deliberately left the files entirely unmodified compared to the upstream versions.

Jess

#18 lore raw

cover Fully support standalone Clang/LLVM toolchains

In reply to Jessica Clarke
Quoted 7 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

Quoted 12 lines

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

Regards,
Bin

#19 lore raw

cover Fully support standalone Clang/LLVM toolchains

Quoted 22 lines · Bin Meng
Quoted 7 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

Quoted 12 lines

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Quoted 3 lines

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

I don?t think such a processor is of interest to OpenSBI; you?re not going to be running any Unix OS on that kind of extremely basic core. We already have assembly that assumes M, and IMA is the documented requirement. If someone really wants to patch OpenSBI to add support for M-less cores then they can either vendor the needed u?{mul,div,mod,divmod}si3 files as well or add back an option to use libgcc/compiler-rt in such a case, but I don?t think that should be an argument for requiring a full libgcc in the only cases supported today that would still be orders of magnitude more common. I?m just following U-Boot*, BBL, TF-A and FreeBSD and Linux kernels in not having a libgcc/compiler-rt dependency; OpenSBI is currently the annoying odd-one-out. And yes, some of those will include full soft-multiply code too, it?s really not that many additional files, though you wouldn?t be able to get them from FreeBSD as it doesn?t support such processors. You could however just adapt its muldi and divdi functions to mulsi and divsi without much difficulty. The alternative is to take files from compiler-rt but the license is Apache with LLVM exceptions so not quite as permissive as the BSD-2/3-clause files in tree today.

My point is, I don?t think we should use improbable hypotheticals as a justification for blocking patches that solve real problems faced today, especially when the solution for those real problems is not incompatible with the hypothetical situations.

Jess

* Currently it requires libgcc/compiler-rt on RISC-V because nobody?s done this yet for its RISC-V port, but other architectures (arc, arm, m68k, mips, powerpc, sh, x86) all have the ability to not use libgcc

#20 lore raw

cover Fully support standalone Clang/LLVM toolchains

Quoted 24 lines · Jessica Clarke
Quoted 22 lines · Bin Meng
Quoted 19 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Quoted 6 lines
Quoted 3 lines

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

I don?t think such a processor is of interest to OpenSBI; you?re not going to be running any Unix OS on that kind of extremely basic core.

We would never know how crazy the vendors might be creating different RISC-V cores to suit different needs. If we only care about the high-end ones, maybe we can just support RV64GC cores. I suspect 32-bit isn't of too much interest to the Linux world (yeah, the 32-bit is broken since Linux kernel v5.12 yet nobody notified this) and/or OpenSBI, why would we bother 32-bit support in OpenSBI?

Quoted 17 lines

We already have assembly that assumes M, and IMA is the documented requirement. If someone really wants to patch OpenSBI to add support for M-less cores then they can either vendor the needed u?{mul,div,mod,divmod}si3 files as well or add back an option to use libgcc/compiler-rt in such a case, but I don?t think that should be an argument for requiring a full libgcc in the only cases supported today that would still be orders of magnitude more common. I?m just following U-Boot*, BBL, TF-A and FreeBSD and Linux kernels in not having a libgcc/compiler-rt dependency; OpenSBI is currently the annoying odd-one-out. And yes, some of those will include full soft-multiply code too, it?s really not that many additional files, though you wouldn?t be able to get them from FreeBSD as it doesn?t support such processors. You could however just adapt its muldi and divdi functions to mulsi and divsi without much difficulty. The alternative is to take files from compiler-rt but the license is Apache with LLVM exceptions so not quite as permissive as the BSD-2/3-clause files in tree today.

Quoted 4 lines

My point is, I don?t think we should use improbable hypotheticals as a justification for blocking patches that solve real problems faced today, especially when the solution for those real problems is not incompatible with the hypothetical situations.

I understand current OpenSBI implementation mandates IMA extensions. But I disagree it's not improbable hypotheticals. M-less core is a valid use case, especially in the embedded world.

Secondly, I was not suggesting this patch set be blocked. It's a pure discussion showing different interests on what flexibility we want to achieve.

Regards,
Bin

#21 lore raw

cover Fully support standalone Clang/LLVM toolchains

In reply to Bin Meng
Quoted 22 lines · Bin Meng
Quoted 7 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

Quoted 12 lines

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Quoted 3 lines

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

We have mandated rv32ima or rv64ima as minimal requirement in docs/platform_requirements.md. The 'I', 'M' and 'A' are very fundamental extensions and we don't want to emulate these extensions in OpenSBI.

Further, a platform must support rv32gc or rv64gc to have platform firmware binaries as-part of OpenSBI release tarball. If a platform supports rv32ima or rv64ima but does not support rv32gc or rv64gc then users have to compile platform firmware binaries from sources.

I think we are okay removing dependency on libgcc. since it allows us to have llvm toolchain support in OpenSBI. Overall, I am quite happy with this series.

Is there a pre-built llvm risc-v toolchain ?? or steps to create one ??

The BSD-2-clause is compatible with the BSD-3-clause used by PATCH2. Am I correct ?

I hope we don't need to specifically mention anything in the "Copyright and License" section of the top-level README.md for BSD-3-clause licensed code ??

Regards,
Anup

#22 lore raw

cover Fully support standalone Clang/LLVM toolchains

Quoted 24 lines · Anup Patel
Quoted 22 lines · Bin Meng
Quoted 19 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Quoted 8 lines
Quoted 3 lines

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

We have mandated rv32ima or rv64ima as minimal requirement in docs/platform_requirements.md. The 'I', 'M' and 'A' are very fundamental extensions and we don't want to emulate these extensions in OpenSBI.

I don't understand why we have to emulate 'M' or 'A' in OpenSBI. It's perfectly okay to run OpenSBI in a uniprocessor environment, all the way up to the operating system which is configured to UP mode. No 'A' extension will be used in the software stack hence no need to emulate 'A'.

Quoted 9 lines

Further, a platform must support rv32gc or rv64gc to have platform firmware binaries as-part of OpenSBI release tarball. If a platform supports rv32ima or rv64ima but does not support rv32gc or rv64gc then users have to compile platform firmware binaries from sources.

I think we are okay removing dependency on libgcc. since it allows us to have llvm toolchain support in OpenSBI. Overall, I am quite happy with this series.

Quoted 8 lines

Is there a pre-built llvm risc-v toolchain ?? or steps to create one ??

The BSD-2-clause is compatible with the BSD-3-clause used by PATCH2. Am I correct ?

I hope we don't need to specifically mention anything in the "Copyright and License" section of the top-level README.md for BSD-3-clause licensed code ??

Regards,
Bin

#23 lore raw

cover Fully support standalone Clang/LLVM toolchains

Quoted 35 lines · Bin Meng
Quoted 24 lines · Anup Patel
Quoted 22 lines · Bin Meng
Quoted 19 lines · Jessica Clarke

This patch series is comprised of two parts.

The first patch adds build system support for using Clang and LLVM binutils, provided your Clang is able to locate a libgcc.a in its search path.

However, pure LLVM toolchains do not use libgcc, they use compiler-rt (libclang_rt.builtins.<arch>.a). We could change the Makefile to not hard-code -lgcc and instead use -print-libgcc-file-name, but that still requires a bare metal compiler-rt built for the right -march/-mabi to be present, which is often not the case. Moreover, we need very little from libgcc/compiler-rt; RV64 needs nothing, and RV32 only needs 64-bit division. Thus, the second patch vendors part of FreeBSD's libquad and stops linking against libgcc entirely, allowing OpenSBI to be built with just a cross-compiler. This means that building with any distro-provided LLVM just works, as does compiling with the system Clang compiler and LLD linker on FreeBSD without any external packages needed (beyond GNU make).

Quoted 8 lines
Quoted 3 lines

I am concerned about removing libgcc. If we want to support running OpenSBI on a processor without M extension, it would require us to link with libgcc, or compiler-rt.

We have mandated rv32ima or rv64ima as minimal requirement in docs/platform_requirements.md. The 'I', 'M' and 'A' are very fundamental extensions and we don't want to emulate these extensions in OpenSBI.

Quoted 5 lines

I don't understand why we have to emulate 'M' or 'A' in OpenSBI. It's perfectly okay to run OpenSBI in a uniprocessor environment, all the way up to the operating system which is configured to UP mode. No 'A' extension will be used in the software stack hence no need to emulate 'A'.

There was a proposal in the past to have 'A' emulated in OpenSBI using LR/SC instructions so we had to define a minimal requirement from platform support in OpenSBI.

The rv32ima and rv64ima requirements came as a subset of requirements enforced by general purpose OSes (like Linux). In fact, Linux RISC-V makefile mandates rv32ima or rv64ima as minimal requirement and there is "NO WAY" to disable 'A' for Linux RISC-V.

I think it makes sense to mandate 'A' for UP systems as well because 'A' instructions can be used by user-space apps on UP systems for inter-thread synchronization. If 'A' is not mandated for a UP system then user-space apps will have to detect and use 'A' instructions or LR/SC whichever is available.

Regards,
Anup

Quoted 21 lines
Quoted 10 lines

Further, a platform must support rv32gc or rv64gc to have platform firmware binaries as-part of OpenSBI release tarball. If a platform supports rv32ima or rv64ima but does not support rv32gc or rv64gc then users have to compile platform firmware binaries from sources.

I think we are okay removing dependency on libgcc. since it allows us to have llvm toolchain support in OpenSBI. Overall, I am quite happy with this series.

Quoted 8 lines

Is there a pre-built llvm risc-v toolchain ?? or steps to create one ??

The BSD-2-clause is compatible with the BSD-3-clause used by PATCH2. Am I correct ?

I hope we don't need to specifically mention anything in the "Copyright and License" section of the top-level README.md for BSD-3-clause licensed code ??

Regards,
Bin