Subject: [patch] 2.4: Support for newer gcc/gas options

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 16 Dec 2003 22:33:41 +0100 (CET)

Hello,

 Since command line options for both gcc and gas has been changed in an 
incompatible way recently and also there are stricter requirements on 
certain options when used simultaneously, I propose the following patch to 
our top-level Makefiles to let the optimal set of options be selected at 
the build time.  The intent is to try modern options first, then obsolete 
ones and to set gas options independently to gcc ones as one may be more 
inclined to upgrade binutils that his old trusty gcc.

 The patch implements a make macro called set_gccflags which accepts two
sets of options consisting of a CPU name and an ISA name each.  Within 
both sets "-march=" and failing that "-mcpu=" is checked with the CPU name 
and the ISA name is checked simultaneously.  For gcc if the first set of 
options fails, the second one is selected even if it would lead to a 
failure.  For gas both sets are checked and if none succeeds, an empty set 
is selected.

 The 32-bit variation accepts a fifth option as well to permit ABI
selection with an ISA when the "-mabi=" option is unavailable, which is 
also tested.

 Beside letting one use modern tools at all the patch also enables CPU
selection using newly added (and closer matching) settings like
"-march=mips64" without forcing users to upgrade tools provided a
conservative fallback is provided.

 Comments, thoughts, opinions, etc. will be appreciated.

  Maciej

-- 
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: [email-masked], PGP key available        +

patch-mips-2.4.23-20031209-march-11
diff -up --recursive --new-file linux-mips-2.4.23-20031209.macro/arch/mips/Makefile linux-mips-2.4.23-20031209/arch/mips/Makefile
--- linux-mips-2.4.23-20031209.macro/arch/mips/Makefile	2003-10-23 02:56:44.000000000 +0000
+++ linux-mips-2.4.23-20031209/arch/mips/Makefile	2003-12-16 11:20:33.000000000 +0000
@@ -5,7 +5,7 @@
 #
 # Copyright (C) 1994, 1995, 1996 by Ralf Baechle
 # DECStation modifications by Paul M. Antoine, 1996
-# Copyright (C) 2002  Maciej W. Rozycki
+# Copyright (C) 2002, 2003  Maciej W. Rozycki
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
@@ -43,7 +43,6 @@ check_gcc = $(shell if $(CC) $(1) -S -o 
 #
 GCCFLAGS	:= -I $(TOPDIR)/include/asm/gcc
 GCCFLAGS	+= -G 0 -mno-abicalls -fno-pic -pipe
-GCCFLAGS	+= $(call check_gcc, -mabi=32,)
 GCCFLAGS	+= $(call check_gcc, -finline-limit=100000,)
 LINKFLAGS	+= -G 0 -static # -N
 MODFLAGS	+= -mlong-calls
@@ -55,56 +54,100 @@ GCCFLAGS	+= -mno-sched-prolog -fno-omit-
 endif
 endif
 
+set_gccflags = $(shell \
+while :; do \
+	cpu=$(1); isa=-$(2); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	cpu=$(3); isa=-$(4); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	break; \
+done; \
+gcc_abi=-mabi=32; gcc_cpu=$$cpu; \
+if $(CC) $$gcc_abi -S -o /dev/null -xc - < /dev/null > /dev/null 2>&1; then \
+	gcc_isa=$$isa; \
+else \
+	gcc_abi=; gcc_isa=-$(5); \
+fi; \
+gas_abi=-Wa,-32; gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \
+while :; do \
+	for gas_opt in -Wa,-march= -Wa,-mcpu=; do \
+		$(CC) $$gas_abi $$gas_opt$$cpu $$gas_isa -c -o /dev/null \
+			-xassembler - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	gas_abi=; gas_opt=; gas_cpu=; gas_isa=; \
+	break; \
+done; \
+echo $$gcc_abi $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_abi $$gas_opt$$gas_cpu $$gas_isa)
+
 # CPU-dependent compiler/assembler options for optimization.
 #
 ifdef CONFIG_CPU_R3000
-GCCFLAGS	+= -mcpu=r3000 -mips1
+GCCFLAGS	+= $(call set_gccflags,r3000,mips1,r3000,mips1,mips1)
 endif
 ifdef CONFIG_CPU_TX39XX
-GCCFLAGS	+= -mcpu=r3000 -mips1
+GCCFLAGS	+= $(call set_gccflags,r3000,mips1,r3000,mips1,mips1)
 endif
 ifdef CONFIG_CPU_R6000
-GCCFLAGS	+= -mcpu=r6000 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r6000,mips2,r6000,mips2,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4300
-GCCFLAGS	+= -mcpu=r4300 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r4300,mips3,r4300,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_VR41XX
-GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r4100,mips3,r4600,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_R4X00
-GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_TX49XX
-GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r4600,mips3,r4600,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_MIPS32
-GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,mips32,mips32,r4600,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_MIPS64
-GCCFLAGS	+= -mcpu=r4600 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,mips64,mips64,r4600,mips3,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5000
-GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r5000,mips4,r5000,mips4,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_R5432
-GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,r5400,mips4,r5000,mips4,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_NEVADA
-# Cannot use -mmad with currently recommended tools
-GCCFLAGS	+= -mcpu=r5000 -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,rm5200,mips4,r5000,mips4,mips2) \
+		   -Wa,--trap
+GCCFLAGS	+= $(call check_gcc,-mmad,)
 endif
 ifdef CONFIG_CPU_RM7000
-GCCFLAGS	+= $(call check_gcc, -march=rm7000, -mcpu=r5000) \
-		   -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,rm7000,mips4,r5000,mips4,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_RM9000
-GCCFLAGS	+= $(call check_gcc, -march=rm9000, -mcpu=r5000) \
-		   -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,rm9000,mips4,r5000,mips4,mips2) \
+		   -Wa,--trap
 endif
 ifdef CONFIG_CPU_SB1
-GCCFLAGS	+= $(call check_gcc, -mcpu=sb1, -mcpu=r5000) \
-		   -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,sb1,mips64,r5000,mips4,mips2) \
+		   -Wa,--trap
 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 MODFLAGS	+= -msb1-pass1-workarounds
 endif
diff -up --recursive --new-file linux-mips-2.4.23-20031209.macro/arch/mips64/Makefile linux-mips-2.4.23-20031209/arch/mips64/Makefile
--- linux-mips-2.4.23-20031209.macro/arch/mips64/Makefile	2003-12-01 03:57:04.000000000 +0000
+++ linux-mips-2.4.23-20031209/arch/mips64/Makefile	2003-12-16 11:22:40.000000000 +0000
@@ -3,7 +3,7 @@
 # License.  See the file "COPYING" in the main directory of this archive
 # for more details.
 #
-# Copyright (C) 2002  Maciej W. Rozycki
+# Copyright (C) 2002, 2003  Maciej W. Rozycki
 #
 # This file is included by the global makefile so that you can add your own
 # architecture-specific flags and dependencies. Remember to do have actions
@@ -11,6 +11,8 @@
 # this architecture
 #
 
+comma := ,
+
 #
 # Select the object file format to substitute into the linker script.
 #
@@ -48,48 +50,73 @@ endif
 endif
 
 check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+check_gas = $(shell if $(CC) $(1) -c -o /dev/null -xassembler - < /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+
+set_gccflags = $(shell \
+while :; do \
+	cpu=$(1); isa=-$(2); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	cpu=$(3); isa=-$(4); \
+	for gcc_opt in -march= -mcpu=; do \
+		$(CC) $$gcc_opt$$cpu $$isa -S -o /dev/null \
+			-xc - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	break; \
+done; \
+gcc_cpu=$$cpu; gcc_isa=$$isa; \
+gas_cpu=$$cpu; gas_isa=-Wa,$$isa; \
+while :; do \
+	for gas_opt in -Wa,-march= -Wa,-mcpu=; do \
+		$(CC) $$gas_opt$$cpu $$gas_isa -c -o /dev/null \
+			-xassembler - < /dev/null > /dev/null 2>&1 && \
+			break 2; \
+	done; \
+	gas_opt=; gas_cpu=; gas_isa=; \
+	break; \
+done; \
+echo $$gcc_opt$$gcc_cpu $$gcc_isa $$gas_opt$$gas_cpu $$gas_isa)
 
 #
 # CPU-dependent compiler/assembler options for optimization.
 #
 ifdef CONFIG_CPU_R4300
-GCCFLAGS	+= -mcpu=r4300 -mips3
+GCCFLAGS	+= $(call set_gccflags,r4300,mips3,r4300,mips3)
 endif
 ifdef CONFIG_CPU_R4X00
-GCCFLAGS	+= -mcpu=r4600 -mips3
+GCCFLAGS	+= $(call set_gccflags,r4600,mips3,r4600,mips3)
 endif
 ifdef CONFIG_CPU_R5000
-GCCFLAGS	+= -mcpu=r8000 -mips4
+GCCFLAGS	+= $(call set_gccflags,r5000,mips4,r8000,mips4)
 endif
 ifdef CONFIG_CPU_NEVADA
-# Cannot use -mmad with currently recommended tools
-GCCFLAGS	+= -mcpu=r8000 -mips3
+GCCFLAGS	+= $(call set_gccflags,rm5200,mips4,r8000,mips4)
+GCCFLAGS	+= $(call check_gcc,-mmad,)
 endif
 ifdef CONFIG_CPU_RM7000
-GCCFLAGS	+= $(call check_gcc, -march=rm7000, -mcpu=r5000) \
-		   -mips2 -Wa,--trap
+GCCFLAGS	+= $(call set_gccflags,rm7000,mips4,r5000,mips4)
+endif
+ifdef CONFIG_CPU_RM9000
+GCCFLAGS	+= $(call set_gccflags,rm9000,mips4,r5000,mips4)
 endif
 ifdef CONFIG_CPU_R8000
-GCCFLAGS	+= -mcpu=r8000 -mips4
+GCCFLAGS	+= $(call set_gccflags,r8000,mips4,r8000,mips4)
 endif
 ifdef CONFIG_CPU_R10000
-GCCFLAGS	+= -mcpu=r8000 -mips4
+GCCFLAGS	+= $(call set_gccflags,r10000,mips4,r8000,mips4)
 endif
 ifdef CONFIG_CPU_SB1
-GCCFLAGS	+= $(call check_gcc, -mcpu=sb1, -mcpu=r5000) -mips4
+GCCFLAGS	+= $(call set_gccflags,sb1,mips64,r5000,mips4)
 ifdef CONFIG_SB1_PASS_1_WORKAROUNDS
 MODFLAGS	+= -msb1-pass1-workarounds
 endif
 endif
 ifdef CONFIG_CPU_MIPS64
-#CFLAGS		+= -mips64	# Should be used then we get a MIPS64 compiler
-CFLAGS		+= -mcpu=r8000 -mips4
-endif
-ifdef CONFIG_CPU_RM7000
-GCCFLAGS	+= -mcpu=r8000 -mips4
-endif
-ifdef CONFIG_CPU_RM9000
-GCCFLAGS	+= -mcpu=r8000 -mips4
+GCCFLAGS	+= $(call set_gccflags,mips64,mips64,r8000,mips4)
 endif
 
 #
@@ -299,7 +326,7 @@ endif
 # convert to ECOFF using elf2ecoff.
 #
 ifdef CONFIG_BOOT_ELF32
-GCCFLAGS += -Wa,-32 $(shell if $(CC) -Wa,-mgp64 -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "-Wa,-mgp64"; fi)
+GCCFLAGS += -Wa,-32 $(call check_gas,-Wa$(comma)-mgp64,)
 LINKFLAGS += -T arch/mips64/ld.script.elf32
 endif
 #
@@ -307,7 +334,7 @@ endif
 # ELF files from 32-bit files by conversion.
 #
 ifdef CONFIG_BOOT_ELF64
-GCCFLAGS += -Wa,-32 $(shell if $(CC) -Wa,-mgp64 -c -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "-Wa,-mgp64"; fi)
+GCCFLAGS += -Wa,-32 $(call check_gas,-Wa$(comma)-mgp64,)
 LINKFLAGS += -T arch/mips64/ld.script.elf32
 #AS += -64
 #LD += -m elf64bmip

---

From: Yoichi Yuasa <[email-masked]>
Date: Wed, 17 Dec 2003 19:57:29 +0900

Hello,

On Tue, 16 Dec 2003 22:33:41 +0100 (CET)

>  Comments, thoughts, opinions, etc. will be appreciated.

This patch is wonderful for vr4100 series!

I'm using "GNU assembler version 2.14.90.0.6".
The gcc option is set up appropriately.

Thanks,

Yoichi

---

From: Atsushi Nemoto <[email-masked]>
Date: Tue, 23 Dec 2003 22:02:13 +0900 (JST)

>>>>> On Tue, 16 Dec 2003 22:33:41 +0100 (CET), "Maciej W. Rozycki" <[email-masked]> said:
macro>  The patch implements a make macro called set_gccflags which
macro> accepts two sets of options consisting of a CPU name and an ISA
macro> name each.  Within both sets "-march=" and failing that
macro> "-mcpu=" is checked with the CPU name and the ISA name is
macro> checked simultaneously.  For gcc if the first set of options
macro> fails, the second one is selected even if it would lead to a
macro> failure.  For gas both sets are checked and if none succeeds,
macro> an empty set is selected.

With this patch, most r4k use MIPS3 ISA, right?

If so, please fix include/asm-mips/asm.h or arch/mips/kernel/entry.S
on 2.4 branch also.

As I wrote in August, handle_adel_int will be broken with MIPS3 ISA.
<http://www.linux-mips.org/archives/linux-mips/2003-08/msg00072.html>

Excerpt from include/asm-mips/asm.h:

#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
    (_MIPS_ISA == _MIPS_ISA_MIPS32)
#define REG_S           sw 
#define REG_L           lw 
#define REG_SUBU        subu
#define REG_ADDU        addu
#endif
#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
#define REG_S           sd
#define REG_L           ld
#define REG_SUBU        dsubu
#define REG_ADDU        daddu
#endif

#if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) || \
    (_MIPS_ISA == _MIPS_ISA_MIPS32)
#define MFC0		mfc0
#define MTC0		mtc0
#endif
#if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) || \
    (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)
#define MFC0		dmfc0
#define MTC0		dmtc0
#endif

Excerpt from arch/mips/kernel/entry.S:

#define __BUILD_clear_ade(exception)                                    \
		.set	reorder;					\
		MFC0	t0,CP0_BADVADDR;                                \
		.set	noreorder;					\
		REG_S	t0,PT_BVADDR(sp);                               \
		KMODE

With MIPS3 ISA, handle_adel_int will be:

8002630c <handle_adel_int> 40284000 	dmfc0	t0,$8
80026310 <handle_adel_int+0x4> 00000000 	nop
80026314 <handle_adel_int+0x8> ffa800a4 	sd	t0,164(sp)

which is wrong for 32bit kernel.

---
Atsushi Nemoto

---

From: "Maciej W. Rozycki" <[email-masked]>
Date: Tue, 23 Dec 2003 14:07:55 +0100 (CET)

> which is wrong for 32bit kernel.

 Which clearly indicates it should be selected with the CONFIG_MIPS32 (or 
CONFIG_MIPS64) option.

 Unfortunately I'm going away right now, so please feel free to fix the
code or alternatively I'll have a fix early in January.

  Maciej

---

From: Thiemo Seufer <[email-masked]>
Date: Tue, 23 Dec 2003 21:44:05 +0100

Atsushi Nemoto wrote:
[snip]
> With this patch, most r4k use MIPS3 ISA, right?

Since -mips2 is retained they actually use -march=r6000 and still
MIPS2 ISA.

>     (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64)

This should use either CONFIG_MIPS{32,64} or the compiler intrinsic
_MIPS_SIM (which did unfortunately change for O32 in gcc 3.4).

Thiemo

---

From: Thiemo Seufer <[email-masked]>
Date: Tue, 23 Dec 2003 23:01:40 +0100

> Since -mips2 is retained they actually use -march=r6000 and still

Well, I should actually read the code instead of speculating. :-)
Now it is -mips3, which means -march=r4000. All _MIPS_ISA defines
abused to check for the O32 ABI are broken now.

Thiemo