Files
lk/arch/riscv/rules.mk
Travis Geiselbrecht 5016118509 [fpu] have the arch layers set WITH_NO_FPU based on the cpu
This will generally turn off more FPU codegen, even if its using
software fallback unless the project/target/platform selects a cpu that
has FPU support. This also turns off a few blocks of test code and the
upcoming floating point printf if it's not present on the arch.

This may break projects that were compiling for say cortex-m0 but
expected FPU code to be present. If so it should be pretty easy to
override it, but not going to add that yet unless it's necessary.
2025-10-08 23:50:53 -07:00

247 lines
7.5 KiB
Makefile

LOCAL_DIR := $(GET_LOCAL_DIR)
MODULE := $(LOCAL_DIR)
MODULE_SRCS += $(LOCAL_DIR)/start.S
MODULE_SRCS += $(LOCAL_DIR)/arch.c
MODULE_SRCS += $(LOCAL_DIR)/asm.S
MODULE_SRCS += $(LOCAL_DIR)/exceptions.c
MODULE_SRCS += $(LOCAL_DIR)/feature.c
MODULE_SRCS += $(LOCAL_DIR)/fpu_asm.S
MODULE_SRCS += $(LOCAL_DIR)/mmu.cpp
MODULE_SRCS += $(LOCAL_DIR)/mp.c
MODULE_SRCS += $(LOCAL_DIR)/sbi.c
MODULE_SRCS += $(LOCAL_DIR)/spinlock.c
MODULE_SRCS += $(LOCAL_DIR)/thread.c
MODULE_SRCS += $(LOCAL_DIR)/time.c
MODULE_DEPS += lib/libcpp
# one file uses slightly complicated designated initializer
MODULE_CFLAGS += -Wno-override-init
SMP_MAX_CPUS ?= 1
RISCV_MMU ?= none
RISCV_FPU ?= false
SUBARCH ?= 32
RISCV_MODE ?= machine
RISCV_EXTENSION_LIST ?=
ARCH_RISCV_EMBEDDED ?= false
ARCH_RISCV_TWOSEGMENT ?= false
GLOBAL_DEFINES += SMP_MAX_CPUS=$(SMP_MAX_CPUS)
GLOBAL_DEFINES += PLATFORM_HAS_DYNAMIC_TIMER=1
ifeq (true,$(call TOBOOL,$(WITH_SMP)))
GLOBAL_DEFINES += WITH_SMP=1
endif
ifeq ($(strip $(RISCV_MODE)),machine)
$(info RISCV: Machine Mode)
GLOBAL_DEFINES += RISCV_M_MODE=1
ifneq ($(RISCV_MMU),none)
$(error RISCV mmu not supported in machine mode)
endif
else ifeq ($(strip $(RISCV_MODE)),supervisor)
$(info RISCV: Supervisor Mode)
GLOBAL_DEFINES += RISCV_S_MODE=1
else
$(error Unknown RISC-V mode: "$(strip $(RISCV_MODE))" (valid values are "machine", "supervisor"))
endif
ifeq ($(RISCV_MMU),sv48)
ifeq ($(SUBARCH),32)
$(error RISCV: sv48 mmu not supported for 32 bit riscv)
endif
$(info RISCV: MMU sv48)
GLOBAL_DEFINES += RISCV_MMU=48
WITH_KERNEL_VM ?= 1
# 48 bits split between two 47 bit halves
KERNEL_ASPACE_BASE := 0xffff800000000000
KERNEL_ASPACE_SIZE := 0x0000800000000000
USER_ASPACE_BASE := 0x0000000001000000
USER_ASPACE_SIZE := 0x00007ffffe000000
else ifeq ($(RISCV_MMU),sv39)
ifeq ($(SUBARCH),32)
$(error RISCV: sv39 mmu not supported for 32 bit riscv)
endif
$(info RISCV: MMU sv39)
GLOBAL_DEFINES += RISCV_MMU=39
WITH_KERNEL_VM ?= 1
# 39 bits split between two 38 bit halves
KERNEL_ASPACE_BASE := 0xffffffc000000000
KERNEL_ASPACE_SIZE := 0x0000004000000000
USER_ASPACE_BASE := 0x0000000001000000
USER_ASPACE_SIZE := 0x0000003ffe000000
else ifeq ($(RISCV_MMU),sv32)
$(info RISCV: MMU sv32)
GLOBAL_DEFINES += RISCV_MMU=32
WITH_KERNEL_VM ?= 1
# 32 bits split between two 31 bit halves
KERNEL_ASPACE_BASE := 0x80000000
KERNEL_ASPACE_SIZE := 0x80000000
USER_ASPACE_BASE := 0x01000000
USER_ASPACE_SIZE := 0x7e000000
else ifeq ($(RISCV_MMU),none)
else
$(error Unknown RISCV_MMU: "$(strip $(RISCV_MMU))" (valid values are "none", "sv32", "sv39", "sv48"))
endif
ifeq (true,$(call TOBOOL,$(WITH_KERNEL_VM)))
GLOBAL_DEFINES += \
ARCH_HAS_MMU=1 \
KERNEL_ASPACE_BASE=$(KERNEL_ASPACE_BASE) \
KERNEL_ASPACE_SIZE=$(KERNEL_ASPACE_SIZE) \
USER_ASPACE_BASE=$(USER_ASPACE_BASE) \
USER_ASPACE_SIZE=$(USER_ASPACE_SIZE)
KERNEL_BASE ?= $(KERNEL_ASPACE_BASE)+$(MEMBASE)
KERNEL_LOAD_OFFSET ?= 0
GLOBAL_DEFINES += KERNEL_BASE=$(KERNEL_BASE)
GLOBAL_DEFINES += KERNEL_LOAD_OFFSET=$(KERNEL_LOAD_OFFSET)
else # no kernel vm
KERNEL_BASE ?= $(MEMBASE)
KERNEL_LOAD_OFFSET ?= 0
endif
ROMBASE ?= 0
GLOBAL_DEFINES += ROMBASE=$(ROMBASE)
GLOBAL_DEFINES += MEMBASE=$(MEMBASE)
GLOBAL_DEFINES += MEMSIZE=$(MEMSIZE)
# if ARCH_riscv{32|64}_TOOLCHAIN_PREFIX is set use it as an override
# for toolchain prefix.
ifdef ARCH_$(ARCH)$(SUBARCH)_TOOLCHAIN_PREFIX
TOOLCHAIN_PREFIX := $(ARCH_$(ARCH)$(SUBARCH)_TOOLCHAIN_PREFIX)
endif
# default toolchain is riscv{32|64}-elf-. assume its in the path.
ifndef TOOLCHAIN_PREFIX
TOOLCHAIN_PREFIX := riscv$(SUBARCH)-elf-
endif
ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
GLOBAL_DEFINES += RISCV_FPU=1
else
GLOBAL_DEFINES += WITH_NO_FP=1
endif
# based on a list of optional extensions passed in, collapse the extensions into
# a string appended to the end of the -march line below
$(info RISCV_EXTENSION_LIST = $(RISCV_EXTENSION_LIST))
ifneq ($(RISCV_EXTENSION_LIST),)
RISCV_MARCH_EXTENSIONS := _$(subst $(SPACE),_,$(RISCV_EXTENSION_LIST))
else
RISCV_MARCH_EXTENSIONS :=
endif
#$(info RISCV_MARCH_EXTENSIONS = $(RISCV_MARCH_EXTENSIONS))
# for the moment simply build all sources the same way, with or without float based on
# the configuration of the platform
ARCH_COMPILEFLAGS_FLOAT :=
ARCH_COMPILEFLAGS_NOFLOAT :=
# based on 32 or 64 bitness, select the right toolchain and some
# compiler codegen flags
ifeq ($(SUBARCH),32)
ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
ARCH_COMPILEFLAGS := -march=rv32gc$(RISCV_MARCH_EXTENSIONS) -mabi=ilp32d
else
ARCH_COMPILEFLAGS := -march=rv32imac$(RISCV_MARCH_EXTENSIONS) -mabi=ilp32
endif
# override machine for ld -r
GLOBAL_MODULE_LDFLAGS += -m elf32lriscv
else ifeq ($(SUBARCH),64)
GLOBAL_DEFINES += IS_64BIT=1
ifeq (true,$(call TOBOOL,$(RISCV_FPU)))
# HACK: use rv64imafdc instead of the equivalent rv64gc due to
# older toolchains not supporting the mapping of one to the other
# when selecting libgcc.
ARCH_COMPILEFLAGS := -march=rv64imafdc$(RISCV_MARCH_EXTENSIONS) -mabi=lp64d -mcmodel=medany
else
ARCH_COMPILEFLAGS := -march=rv64imac$(RISCV_MARCH_EXTENSIONS) -mabi=lp64 -mcmodel=medany
endif
# override machine for ld -r
GLOBAL_MODULE_LDFLAGS += -m elf64lriscv
else
$(error SUBARCH not set or set to something unknown)
endif
# test to see if -misa-spec=2.2 is a valid switch.
# misa-spec is added to make sure the compiler picks up the zicsr extension by default.
# If CC is being overridden by the user, use that instead of the toolchain gcc.
ifdef CC
MISA_SPEC := $(shell $(CC) $(ARCH_COMPILEFLAGS) -misa-spec=2.2 -E - < /dev/null > /dev/null 2>1 && echo supported)
else
MISA_SPEC := $(shell $(TOOLCHAIN_PREFIX)gcc $(ARCH_COMPILEFLAGS) -misa-spec=2.2 -E - < /dev/null > /dev/null 2>1 && echo supported)
endif
$(info MISA_SPEC = $(MISA_SPEC))
ifeq ($(MISA_SPEC),supported)
ARCH_COMPILEFLAGS += -misa-spec=2.2
endif
# embedded switch sets the default compile optimization and passes
# a flag to the code to switch other things on
ifeq (true,$(call TOBOOL,$(ARCH_RISCV_EMBEDDED)))
ARCH_OPTFLAGS ?= -Os
GLOBAL_DEFINES += ARCH_RISCV_EMBEDDED=1
WITH_LINKER_GC ?= 1
else
ARCH_OPTFLAGS ?= -O2
WITH_LINKER_GC ?= 0
endif
LIBGCC := $(shell $(TOOLCHAIN_PREFIX)gcc $(GLOBAL_COMPILEFLAGS) $(ARCH_COMPILEFLAGS) $(GLOBAL_CFLAGS) -print-libgcc-file-name)
$(info LIBGCC = $(LIBGCC))
# potentially generated files that should be cleaned out with clean make rule
GENERATED += \
$(BUILDDIR)/linker-onesegment.ld \
$(BUILDDIR)/linker-twosegment.ld
# rules for generating the linker script
$(BUILDDIR)/linker-%.ld: $(LOCAL_DIR)/linker-%.ld $(wildcard arch/*.ld) linkerscript.phony
@echo generating $@
@$(MKDIR)
$(NOECHO)sed "s/%BITS%/$(SUBARCH)/g;s/%ROMBASE%/$(ROMBASE)/;s/%MEMBASE%/$(MEMBASE)/;s/%MEMSIZE%/$(MEMSIZE)/;s/%KERNEL_BASE%/$(KERNEL_BASE)/;s/%KERNEL_LOAD_OFFSET%/$(KERNEL_LOAD_OFFSET)/" < $< > $@.tmp
@$(call TESTANDREPLACEFILE,$@.tmp,$@)
linkerscript.phony:
.PHONY: linkerscript.phony
# select the appropriate linker script based on if we're a one or two segment system
ifeq (true,$(call TOBOOL,$(ARCH_RISCV_TWOSEGMENT)))
GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=1
LINKER_SCRIPT += $(BUILDDIR)/linker-twosegment.ld
# set MAXPAGESIZE to 8 to cause the linker script to pack things in much tighter than
# a paged sytem would.
# NOTE: 8 seems to be about as far as you can go. experienced some extra stuffed words
# when using 4.
ARCH_LDFLAGS += -z max-page-size=8
else
GLOBAL_DEFINES += ARCH_RISCV_TWOSEGMENT=0
LINKER_SCRIPT += $(BUILDDIR)/linker-onesegment.ld
endif
$(info ARCH_COMPILEFLAGS = $(ARCH_COMPILEFLAGS))
include make/module.mk
# vim: set ts=4 sw=4 expandtab: