@@ -563,30 +563,24 @@ endif
563563# # RISCV (32-bit)
564564ifeq ($(ARCH ) ,RISCV)
565565 CROSS_COMPILE? =riscv32-unknown-elf-
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.
566+ # GCC 12+ separated _zicsr (CSR instructions) and _zifencei (fence.i)
567+ # from the base "I" extension, requiring them to be listed explicitly in
568+ # the -march string. Detect with compile-only tests (-c).
569+ #
570+ # IMPORTANT: these extensions are added to CFLAGS only (compilation).
571+ # They must NOT appear in LDFLAGS because GCC 15 decomposes the ISA
572+ # string (m→zmmul, a→zaamo+zalrsc, c→zca) producing an expanded
573+ # -march that has no matching multilib, causing a fatal error at
574+ # link time. The base march is multilib-safe for all GCC versions.
570575 RISCV32_ZICSR := $(shell echo "void _start(void) {}" | \
571576 $(CROSS_COMPILE ) gcc -march=rv32imac_zicsr -mabi=ilp32 -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
572577 RISCV32_ZIFENCEI := $(shell echo "void _start(void) {}" | \
573578 $(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- # Link test using 64-bit integer division to force libgcc resolution.
576- # A trivial void _start(){} never references libgcc, hiding ABI
577- # mismatches (e.g., GCC 15 falling back to double-float libgcc).
578- RISCV32_EXT_LINK_OK := $(shell echo 'long long _d(long long a,long long b) {return a/b;}void _start(void){_d(0,1);}' | \
579- $(CROSS_COMPILE ) gcc -march=rv32imac$(RISCV32_ZICSR )$(RISCV32_ZIFENCEI ) \
580- -mabi=ilp32 -nostartfiles -x c - -o /dev/null 2>/dev/null && echo ok)
581- ifneq ($(RISCV32_EXT_LINK_OK),ok)
582- RISCV32_ZICSR :=
583- RISCV32_ZIFENCEI :=
584- endif
585- endif
586- ARCH_FLAGS=-march =rv32imac$(RISCV32_ZICSR )$(RISCV32_ZIFENCEI ) -mabi=ilp32 -mcmodel=medany
587579 CFLAGS+ =-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV
588- CFLAGS+ =$(ARCH_FLAGS )
589- LDFLAGS+ =$(ARCH_FLAGS )
580+ # Compilation: extended march so assembler accepts CSR/fence.i
581+ CFLAGS+=-march =rv32imac$(RISCV32_ZICSR )$(RISCV32_ZIFENCEI ) -mabi=ilp32 -mcmodel=medany
582+ # Linking: base march (no extension suffixes) for multilib lookup
583+ LDFLAGS+=-march =rv32imac -mabi=ilp32 -mcmodel=medany
590584 MATH_OBJS += $(WOLFBOOT_LIB_WOLFSSL ) /wolfcrypt/src/sp_c32.o
591585
592586 # Prune unused functions and data
@@ -632,30 +626,22 @@ ifeq ($(ARCH),RISCV64)
632626 UPDATE_OBJS? =src/update_ram.o
633627 endif
634628
635- # Detect zicsr/zifencei support with link verification (see RV32 comment)
629+ # GCC 12+ extension detection (see RISCV 32-bit section above).
630+ # Extensions go in CFLAGS only; LDFLAGS uses the base march to avoid
631+ # GCC 15 multilib lookup failures from ISA string decomposition.
636632 RISCV64_ZICSR := $(shell echo "void _start(void) {}" | \
637633 $(CROSS_COMPILE ) gcc -march=rv64imafd_zicsr -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zicsr)
638634 RISCV64_ZIFENCEI := $(shell echo "void _start(void) {}" | \
639635 $(CROSS_COMPILE ) gcc -march=rv64imafd_zifencei -mabi=lp64d -c -x c - -o /dev/null 2>/dev/null && echo _zifencei)
640- ifneq ($(RISCV64_ZICSR)$(RISCV64_ZIFENCEI),)
641- # Link test using 128-bit integer division to force libgcc resolution.
642- # A trivial void _start(){} never references libgcc, hiding multilib
643- # mismatches (e.g., GCC 15 arch decomposition breaking multilib lookup).
644- RISCV64_EXT_LINK_OK := $(shell echo '__int128 _d(__int128 a,__int128 b) {return a/b;}void _start(void){_d(0,1);}' | \
645- $(CROSS_COMPILE ) gcc -march=rv64imafd$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) \
646- -mabi=lp64d -nostartfiles -x c - -o /dev/null 2>/dev/null && echo ok)
647- ifneq ($(RISCV64_EXT_LINK_OK),ok)
648- RISCV64_ZICSR :=
649- RISCV64_ZIFENCEI :=
650- endif
651- endif
652636
653637 ifeq ($(RISCV_MMODE),1)
654638 # E51 core: rv64imac (no FPU, no crypto extensions)
655- ARCH_FLAGS=-march =rv64imac$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) -mabi=lp64 -mcmodel=medany
639+ CFLAGS+=-march =rv64imac$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) -mabi=lp64 -mcmodel=medany
640+ LDFLAGS+=-march =rv64imac -mabi=lp64 -mcmodel=medany
656641 else
657642 # U54 cores: rv64gc (with FPU)
658- ARCH_FLAGS=-march =rv64imafd$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) -mabi=lp64d -mcmodel=medany
643+ CFLAGS+=-march =rv64imafd$(RISCV64_ZICSR )$(RISCV64_ZIFENCEI ) -mabi=lp64d -mcmodel=medany
644+ LDFLAGS+=-march =rv64imafd -mabi=lp64d -mcmodel=medany
659645
660646 # FDT support for DDR S-mode (not needed for L2-LIM bare-metal boot)
661647 ifneq ($(MPFS_L2LIM),1)
@@ -664,8 +650,6 @@ ifeq ($(ARCH),RISCV64)
664650 endif
665651 endif
666652 CFLAGS+ =-fno-builtin-printf -DUSE_M_TIME -g -nostartfiles -DARCH_RISCV -DARCH_RISCV64
667- CFLAGS+ =$(ARCH_FLAGS )
668- LDFLAGS+ =$(ARCH_FLAGS )
669653
670654 # Prune unused functions and data
671655 CFLAGS +=-ffunction-sections -fdata-sections
0 commit comments