@@ -563,13 +563,23 @@ endif
563563# # RISCV (32-bit)
564564ifeq ($(ARCH ) ,RISCV)
565565 CROSS_COMPILE? =riscv32-unknown-elf-
566- # GCC 12-14 split CSR/fence.i into separate extensions (zicsr, zifencei)
567- # and require them explicitly. GCC 15+ re-implies them, and adding them
568- # explicitly can cause multilib lookup failures. Detect by testing if a
569- # CSR/fence.i instruction assembles WITHOUT the extension flag. If it
570- # fails, add the extension.
571- RISCV32_ZICSR := $(shell echo "void f(void) {__asm__ volatile(\"csrr a0,mhartid\");}" | $(CROSS_COMPILE ) gcc -march=rv32imac -mabi=ilp32 -x c -c - -o /dev/null 2>/dev/null || echo _zicsr)
572- RISCV32_ZIFENCEI := $(shell echo "void f(void) {__asm__ volatile(\"fence.i\");}" | $(CROSS_COMPILE ) gcc -march=rv32imac -mabi=ilp32 -x c -c - -o /dev/null 2>/dev/null || echo _zifencei)
566+ # Detect zicsr/zifencei support: GCC 12+ may require these extensions
567+ # explicitly. However, GCC 15 decomposes arch strings (m→zmmul,
568+ # a→zaamo+zalrsc, c→zca) which can break multilib lookup.
569+ # Verify with a link test, not just compile, to catch multilib mismatches.
570+ RISCV32_ZICSR := $(shell echo "void _start(void) {}" | \
571+ $(CROSS_COMPILE ) gcc -march=rv32imac_zicsr -mabi=ilp32 -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
572+ RISCV32_ZIFENCEI := $(shell echo "void _start(void) {}" | \
573+ $(CROSS_COMPILE ) gcc -march=rv32imac_zifencei -mabi=ilp32 -c -x c - -o /dev/null 2>/dev/null && echo _zifencei)
574+ ifneq ($(RISCV32_ZICSR)$(RISCV32_ZIFENCEI),)
575+ RISCV32_EXT_LINK_OK := $(shell echo "void _start(void) {}" | \
576+ $(CROSS_COMPILE ) gcc -march=rv32imac$(RISCV32_ZICSR )$(RISCV32_ZIFENCEI ) \
577+ -mabi=ilp32 -nostartfiles -x c - -o /dev/null 2>/dev/null && echo ok)
578+ ifneq ($(RISCV32_EXT_LINK_OK),ok)
579+ RISCV32_ZICSR :=
580+ RISCV32_ZIFENCEI :=
581+ endif
582+ endif
573583 ARCH_FLAGS=-march =rv32imac$(RISCV32_ZICSR )$(RISCV32_ZIFENCEI ) -mabi=ilp32 -mcmodel=medany
574584 CFLAGS+ =-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV
575585 CFLAGS+ =$(ARCH_FLAGS )
@@ -619,13 +629,20 @@ ifeq ($(ARCH),RISCV64)
619629 UPDATE_OBJS? =src/update_ram.o
620630 endif
621631
622- # GCC 12-14 split CSR/fence.i into separate extensions (zicsr, zifencei)
623- # and require them explicitly. GCC 15+ re-implies them, and adding them
624- # explicitly can cause multilib lookup failures. Detect by testing if a
625- # CSR/fence.i instruction assembles WITHOUT the extension flag. If it
626- # fails, add the extension.
627- RISCV64_ZICSR := $(shell echo "void f(void) {__asm__ volatile(\"csrr a0,mhartid\");}" | $(CROSS_COMPILE ) gcc -march=rv64imac -mabi=lp64 -x c -c - -o /dev/null 2>/dev/null || echo _zicsr)
628- RISCV64_ZIFENCEI := $(shell echo "void f(void) {__asm__ volatile(\"fence.i\");}" | $(CROSS_COMPILE ) gcc -march=rv64imac -mabi=lp64 -x c -c - -o /dev/null 2>/dev/null || echo _zifencei)
632+ # Detect zicsr/zifencei support with link verification (see RV32 comment)
633+ RISCV64_ZICSR := $(shell echo "void _start(void) {}" | \
634+ $(CROSS_COMPILE ) gcc -march=rv64imafd_zicsr -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
635+ RISCV64_ZIFENCEI := $(shell echo "void _start(void) {}" | \
636+ $(CROSS_COMPILE ) gcc -march=rv64imafd_zifencei -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zifencei)
637+ ifneq ($(RISCV64_ZICSR)$(RISCV64_ZIFENCEI),)
638+ RISCV64_EXT_LINK_OK := $(shell echo "void _start(void) {}" | \
639+ $(CROSS_COMPILE ) gcc -march=rv64imafd$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) \
640+ -mabi=lp64d -nostartfiles -x c - -o /dev/null 2>/dev/null && echo ok)
641+ ifneq ($(RISCV64_EXT_LINK_OK),ok)
642+ RISCV64_ZICSR :=
643+ RISCV64_ZIFENCEI :=
644+ endif
645+ endif
629646
630647 ifeq ($(RISCV_MMODE),1)
631648 # E51 core: rv64imac (no FPU, no crypto extensions)
0 commit comments