Skip to contentSkip to conversation

MIPS: fix build with binutils 2.24.51+

RFC PATCH Superseded Manuel Lauss 3 participants 6 messages Oct 11, 2014 – Oct 23, 2014 MIPS

v3 of 7 Superseded Latest is v7 →

lore
Share & tools
lore
#0 lore raw

RFC PATCH v3 1/1 MIPS: fix build with binutils 2.24.51+

Starting with version 2.24.51.20140728 MIPS binutils complain loudly about mixing soft-float and hard-float object files, leading to this build failure since GCC is invoked with "-msoft-float" on MIPS:

{standard input}: Warning: .gnu_attribute 4,3 requires `softfloat'
LD arch/mips/alchemy/common/built-in.o
mipsel-softfloat-linux-gnu-ld: Warning: arch/mips/alchemy/common/built-in.o
uses -msoft-float (set by arch/mips/alchemy/common/prom.o), arch/mips/alchemy/common/sleeper.o uses -mhard-float

To fix this, we detect if GAS is new enough to support "-msoft-float" command option, and if it does, we can let GCC pass it to GAS; but then we also need to sprinkle the files which make use of floating point registers with the necessary ".set hardfloat" directives.

---
I've only tested a mips32r1 build, but at least binutils-2.23 and a snapshot from today (with the MIPS fp changes) compile a bootable kernel.

Tests on 64bit and with MSA and other extensions also appreciated!

v3: incorporate Maciej's suggestions:
- detect if gas can handle -msoft-float and ".set hardfloat"
- apply .set hardfloat only where really necessary

v2: cover more files

This was introduced in binutils commit 351cdf24d223290b15fa991e5052ec9e9bd1e284 ("[MIPS] Implement O32 FPXX, FP64 and FP64A ABI extensions").

 arch/mips/Makefile                  |  9 +++++++++
 arch/mips/include/asm/asmmacro-32.h |  5 +++++
 arch/mips/include/asm/asmmacro.h    | 18 ++++++++++++++++++
 arch/mips/include/asm/fpregdef.h    | 14 ++++++++++++++
 arch/mips/include/asm/mipsregs.h    | 19 +++++++++++++++++++
 arch/mips/kernel/genex.S            |  1 +
 arch/mips/kernel/r2300_switch.S     |  5 +++++
 arch/mips/kernel/r4k_fpu.S          |  7 +++++++
 arch/mips/kernel/r4k_switch.S       |  9 +++++++++
 arch/mips/kernel/r6000_fpu.S        |  5 +++++
 10 files changed, 92 insertions(+)
arch/mips/Makefile +9 -0
index bbac51e1..35005e1 100644
@@ -93,6 +93,15 @@ LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
 KBUILD_AFLAGS_MODULE		+= -mlong-calls
 KBUILD_CFLAGS_MODULE		+= -mlong-calls
 
+#
+# pass -msoft-float to GAS if it supports it.  However on newer binutils
+# (specifically newer than 2.24.51.20140728) we then also need to explicitly
+# set ".set hardfloat" in all files which manipulate floating point registers.
+#
+ifneq ($(call as-option,-Wa$(comma)-msoft-float,),)
+	cflags-y		+= -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float
+endif
+
 cflags-y += -ffreestanding
 
 #
arch/mips/include/asm/asmmacro-32.h +5 -0
index e38c281..a97ce53 100644
@@ -12,6 +12,9 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
+	.set push
+	SET_HARDFLOAT
+
 	.macro	fpu_save_single thread tmp=t0
 	cfc1	\tmp,  fcr31
 	swc1	$f0,  THREAD_FPR0_LS64(\thread)
@@ -86,6 +89,8 @@
 	ctc1	\tmp, fcr31
 	.endm
 
+	.set pop
+
 	.macro	cpu_save_nonscratch thread
 	LONG_S	s0, THREAD_REG16(\thread)
 	LONG_S	s1, THREAD_REG17(\thread)
arch/mips/include/asm/asmmacro.h +18 -0
index cd9a98b..6caf876 100644
@@ -57,6 +57,8 @@
 #endif /* CONFIG_CPU_MIPSR2 */
 
 	.macro	fpu_save_16even thread tmp=t0
+	.set	push
+	SET_HARDFLOAT
 	cfc1	\tmp, fcr31
 	sdc1	$f0,  THREAD_FPR0_LS64(\thread)
 	sdc1	$f2,  THREAD_FPR2_LS64(\thread)
@@ -75,11 +77,13 @@
 	sdc1	$f28, THREAD_FPR28_LS64(\thread)
 	sdc1	$f30, THREAD_FPR30_LS64(\thread)
 	sw	\tmp, THREAD_FCR31(\thread)
+	.set	pop
 	.endm
 
 	.macro	fpu_save_16odd thread
 	.set	push
 	.set	mips64r2
+	SET_HARDFLOAT
 	sdc1	$f1,  THREAD_FPR1_LS64(\thread)
 	sdc1	$f3,  THREAD_FPR3_LS64(\thread)
 	sdc1	$f5,  THREAD_FPR5_LS64(\thread)
@@ -110,6 +114,8 @@
 	.endm
 
 	.macro	fpu_restore_16even thread tmp=t0
+	.set	push
+	SET_HARDFLOAT
 	lw	\tmp, THREAD_FCR31(\thread)
 	ldc1	$f0,  THREAD_FPR0_LS64(\thread)
 	ldc1	$f2,  THREAD_FPR2_LS64(\thread)
@@ -133,6 +139,7 @@
 	.macro	fpu_restore_16odd thread
 	.set	push
 	.set	mips64r2
+	SET_HARDFLOAT
 	ldc1	$f1,  THREAD_FPR1_LS64(\thread)
 	ldc1	$f3,  THREAD_FPR3_LS64(\thread)
 	ldc1	$f5,  THREAD_FPR5_LS64(\thread)
@@ -277,6 +284,7 @@
 	.macro	cfcmsa	rd, cs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	CFC_MSA_INSN | (\cs << 11)
 	move	\rd, $1
@@ -286,6 +294,7 @@
 	.macro	ctcmsa	cd, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	move	$1, \rs
 	.word	CTC_MSA_INSN | (\cd << 6)
 	.set	pop
@@ -294,6 +303,7 @@
 	.macro	ld_d	wd, off, base
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	add	$1, \base, \off
 	.word	LDD_MSA_INSN | (\wd << 6)
 	.set	pop
@@ -302,6 +312,7 @@
 	.macro	st_d	wd, off, base
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	add	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
@@ -310,6 +321,7 @@
 	.macro	copy_u_w	rd, ws, n
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
 	/* move triggers an assembler bug... */
@@ -320,6 +332,7 @@
 	.macro	copy_u_d	rd, ws, n
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
 	/* move triggers an assembler bug... */
@@ -330,6 +343,7 @@
 	.macro	insert_w	wd, n, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	/* move triggers an assembler bug... */
 	or	$1, \rs, zero
 	.word	INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
@@ -339,6 +353,7 @@
 	.macro	insert_d	wd, n, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	/* move triggers an assembler bug... */
 	or	$1, \rs, zero
 	.word	INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
@@ -381,6 +396,7 @@
 	st_d	31, THREAD_FPR31, \thread
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	cfcmsa	$1, MSA_CSR
 	sw	$1, THREAD_MSA_CSR(\thread)
 	.set	pop
@@ -389,6 +405,7 @@
 	.macro	msa_restore_all	thread
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	lw	$1, THREAD_MSA_CSR(\thread)
 	ctcmsa	MSA_CSR, $1
 	.set	pop
@@ -441,6 +458,7 @@
 	.macro	msa_init_all_upper
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	not	$1, zero
 	msa_init_upper	0
 	.set	pop
arch/mips/include/asm/fpregdef.h +14 -0
index 429481f..f184ba0 100644
@@ -14,6 +14,20 @@
 
 #include <asm/sgidefs.h>
 
+/*
+ * starting with binutils 2.24.51.20140729, MIPS binutils warn about mixing
+ * hardfloat and softfloat object files.  The kernel build uses soft-float by
+ * default, so we also need to pass -msoft-float along to GAS if it supports it.
+ * But this in turn causes assembler errors in files which access hardfloat
+ * registers.  We detect if GAS supports "-msoft-float" in the Makefile and
+ * explicitly put ".set hardfloat" where floating point registers are touched.
+ */
+#ifdef GAS_HAS_SET_HARDFLOAT
+#define SET_HARDFLOAT .set hardfloat
+#else
+#define SET_HARDFLOAT
+#endif
+
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 
 /*
arch/mips/include/asm/mipsregs.h +19 -0
index cf3b580..889c012 100644
@@ -1324,6 +1324,7 @@ do {									\
 /*
  * Macros to access the floating point coprocessor control registers
  */
+#ifdef GAS_HAS_SET_HARDFLOAT
 #define read_32bit_cp1_register(source)					\
 ({									\
 	int __res;							\
@@ -1334,11 +1335,29 @@ do {									\
 	"	# gas fails to assemble cfc1 for some archs,	\n"	\
 	"	# like Octeon.					\n"	\
 	"	.set	mips1					\n"	\
+	"	.set	hardfloat				\n"	\
 	"	cfc1	%0,"STR(source)"			\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 	__res;								\
 })
+#else
+#define read_32bit_cp1_register(source)					\
+({									\
+	int __res;							\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	reorder					\n"	\
+	"	# gas fails to assemble cfc1 for some archs,	\n"	\
+	"	# like Octeon.					\n"	\
+	"	.set	mips1					\n"	\
+	"	cfc1	%0,"STR(source)"			\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+	__res;								\
+})
+#endif
 
 #ifdef HAVE_AS_DSP
 #define rddsp(mask)							\
arch/mips/kernel/genex.S +1 -0
index ac35e12..a5e26dd 100644
@@ -358,6 +358,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	.set	push
 	/* gas fails to assemble cfc1 for some archs (octeon).*/ \
 	.set	mips1
+	SET_HARDFLOAT
 	cfc1	a1, fcr31
 	li	a2, ~(0x3f << 12)
 	and	a2, a1
arch/mips/kernel/r2300_switch.S +5 -0
index 20b7b04..435ea65 100644
@@ -120,6 +120,9 @@ LEAF(_restore_fp)
 
 #define FPU_DEFAULT  0x00000000
 
+	.set push
+	SET_HARDFLOAT
+
 LEAF(_init_fpu)
 	mfc0	t0, CP0_STATUS
 	li	t1, ST0_CU1
@@ -165,3 +168,5 @@ LEAF(_init_fpu)
 	mtc1	t0, $f31
 	jr	ra
 	END(_init_fpu)
+
+	.set pop
arch/mips/kernel/r4k_fpu.S +7 -0
index 8352523..4a827a3 100644
@@ -21,6 +21,7 @@
 
 	.macro	EX insn, reg, src
 	.set	push
+	SET_HARDFLOAT
 	.set	nomacro
 .ex\@:	\insn	\reg, \src
 	.set	pop
@@ -33,7 +34,10 @@
 	.set	arch=r4000
 
 LEAF(_save_fp_context)
+	.set	push
+	SET_HARDFLOAT
 	cfc1	t1, fcr31
+	.set	pop
 
 #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
 	.set	push
@@ -191,7 +195,10 @@ LEAF(_restore_fp_context)
 	EX	ldc1 $f26, SC_FPREGS+208(a0)
 	EX	ldc1 $f28, SC_FPREGS+224(a0)
 	EX	ldc1 $f30, SC_FPREGS+240(a0)
+	.set push
+	SET_HARDFLOAT
 	ctc1	t1, fcr31
+	.set pop
 	jr	ra
 	 li	v0, 0					# success
 	END(_restore_fp_context)
arch/mips/kernel/r4k_switch.S +9 -0
index 4c4ec18..6467a8b 100644
@@ -65,8 +65,12 @@
 	bgtz	a3, 1f
 
 	/* Save 128b MSA vector context + scalar FP control & status. */
+	.set push
+	SET_HARDFLOAT
 	cfc1	t1, fcr31
 	msa_save_all	a0
+	.set pop	/* SET_HARDFLOAT */
+
 	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
@@ -161,6 +165,9 @@ LEAF(_init_msa_upper)
 
 #define FPU_DEFAULT  0x00000000
 
+	.set push
+	SET_HARDFLOAT
+
 LEAF(_init_fpu)
 	mfc0	t0, CP0_STATUS
 	li	t1, ST0_CU1
@@ -291,3 +298,5 @@ LEAF(_init_fpu)
 #endif
 	jr	ra
 	END(_init_fpu)
+
+	.set pop	/* SET_HARDFLOAT */
arch/mips/kernel/r6000_fpu.S +5 -0
index da0fbe4..4707738 100644
@@ -18,6 +18,9 @@
 
 	.set	noreorder
 	.set	mips2
+	.set	push
+	SET_HARDFLOAT
+
 	/* Save floating point context */
 	LEAF(_save_fp_context)
 	mfc0	t0,CP0_STATUS
@@ -85,3 +88,5 @@
 1:	jr	ra
 	 nop
 	END(_restore_fp_context)
+
+	.set pop	/* SET_HARDFLOAT */

--
2.1.2

#1 lore raw
Quoted 32 lines · Manuel Lauss

Starting with version 2.24.51.20140728 MIPS binutils complain loudly about mixing soft-float and hard-float object files, leading to this build failure since GCC is invoked with "-msoft-float" on MIPS:

{standard input}: Warning: .gnu_attribute 4,3 requires `softfloat'
LD arch/mips/alchemy/common/built-in.o
mipsel-softfloat-linux-gnu-ld: Warning: arch/mips/alchemy/common/built-in.o
uses -msoft-float (set by arch/mips/alchemy/common/prom.o), arch/mips/alchemy/common/sleeper.o uses -mhard-float

To fix this, we detect if GAS is new enough to support "-msoft-float" command option, and if it does, we can let GCC pass it to GAS; but then we also need to sprinkle the files which make use of floating point registers with the necessary ".set hardfloat" directives.

---
I've only tested a mips32r1 build, but at least binutils-2.23 and a snapshot from today (with the MIPS fp changes) compile a bootable kernel.

Tests on 64bit and with MSA and other extensions also appreciated!

v3: incorporate Maciej's suggestions:
- detect if gas can handle -msoft-float and ".set hardfloat"
- apply .set hardfloat only where really necessary

v2: cover more files

This was introduced in binutils commit 351cdf24d223290b15fa991e5052ec9e9bd1e284 ("[MIPS] Implement O32 FPXX, FP64 and FP64A ABI extensions").

Quoted 12 lines
 arch/mips/Makefile                  |  9 +++++++++
 arch/mips/include/asm/asmmacro-32.h |  5 +++++
 arch/mips/include/asm/asmmacro.h    | 18 ++++++++++++++++++
 arch/mips/include/asm/fpregdef.h    | 14 ++++++++++++++
 arch/mips/include/asm/mipsregs.h    | 19 +++++++++++++++++++
 arch/mips/kernel/genex.S            |  1 +
 arch/mips/kernel/r2300_switch.S     |  5 +++++
 arch/mips/kernel/r4k_fpu.S          |  7 +++++++
 arch/mips/kernel/r4k_switch.S       |  9 +++++++++
 arch/mips/kernel/r6000_fpu.S        |  5 +++++
 10 files changed, 92 insertions(+)

Hi,

I applied this patch but it still does not build for me on a malta_defconfig:

arch/mips/kernel/r4k_fpu.S: Assembler messages:
arch/mips/kernel/r4k_fpu.S:52: Error: float register should be even, was 1 arch/mips/kernel/r4k_fpu.S:53: Error: float register should be even, was 3 arch/mips/kernel/r4k_fpu.S:54: Error: float register should be even, was 5 arch/mips/kernel/r4k_fpu.S:55: Error: float register should be even, was 7
...

The error is different this time so we probably need a follow-up patch

Signature · 1 line
markos
#2 lore raw
Quoted 50 lines · Markos Chandras
Quoted 32 lines · Manuel Lauss

Starting with version 2.24.51.20140728 MIPS binutils complain loudly about mixing soft-float and hard-float object files, leading to this build failure since GCC is invoked with "-msoft-float" on MIPS:

{standard input}: Warning: .gnu_attribute 4,3 requires `softfloat'
LD arch/mips/alchemy/common/built-in.o
mipsel-softfloat-linux-gnu-ld: Warning: arch/mips/alchemy/common/built-in.o
uses -msoft-float (set by arch/mips/alchemy/common/prom.o), arch/mips/alchemy/common/sleeper.o uses -mhard-float

To fix this, we detect if GAS is new enough to support "-msoft-float" command option, and if it does, we can let GCC pass it to GAS; but then we also need to sprinkle the files which make use of floating point registers with the necessary ".set hardfloat" directives.

---
I've only tested a mips32r1 build, but at least binutils-2.23 and a snapshot from today (with the MIPS fp changes) compile a bootable kernel.

Tests on 64bit and with MSA and other extensions also appreciated!

v3: incorporate Maciej's suggestions:
- detect if gas can handle -msoft-float and ".set hardfloat"
- apply .set hardfloat only where really necessary

v2: cover more files

This was introduced in binutils commit 351cdf24d223290b15fa991e5052ec9e9bd1e284 ("[MIPS] Implement O32 FPXX, FP64 and FP64A ABI extensions").

Quoted 12 lines
 arch/mips/Makefile                  |  9 +++++++++
 arch/mips/include/asm/asmmacro-32.h |  5 +++++
 arch/mips/include/asm/asmmacro.h    | 18 ++++++++++++++++++
 arch/mips/include/asm/fpregdef.h    | 14 ++++++++++++++
 arch/mips/include/asm/mipsregs.h    | 19 +++++++++++++++++++
 arch/mips/kernel/genex.S            |  1 +
 arch/mips/kernel/r2300_switch.S     |  5 +++++
 arch/mips/kernel/r4k_fpu.S          |  7 +++++++
 arch/mips/kernel/r4k_switch.S       |  9 +++++++++
 arch/mips/kernel/r6000_fpu.S        |  5 +++++
 10 files changed, 92 insertions(+)

Hi,

I applied this patch but it still does not build for me on a malta_defconfig:

Quoted 9 lines

arch/mips/kernel/r4k_fpu.S: Assembler messages:
arch/mips/kernel/r4k_fpu.S:52: Error: float register should be even, was 1 arch/mips/kernel/r4k_fpu.S:53: Error: float register should be even, was 3 arch/mips/kernel/r4k_fpu.S:54: Error: float register should be even, was 5 arch/mips/kernel/r4k_fpu.S:55: Error: float register should be even, was 7
...

The error is different this time so we probably need a follow-up patch

I also get a problem with an older version of binutils (the one from the latest Sourcery CodeBench toolchain[1])

{standard input}: Assembler messages:
{standard input}:406: Error: opcode not supported on this processor:
mips1 (mips1) `cfc1 $9,$31'
scripts/Makefile.build:257: recipe for target 'arch/mips/kernel/branch.o' failed
make[2]: *** [arch/mips/kernel/branch.o] Error 1

[1] https://sourcery.mentor.com/GNUToolchain/release2791

Signature · 1 line
markos
#3 lore raw
In reply to Manuel Lauss

(top posting so Matthew can see the entire patch)

+CC Matthew Fortune who has some comments on the patch.

Quoted 409 lines · Manuel Lauss

Starting with version 2.24.51.20140728 MIPS binutils complain loudly about mixing soft-float and hard-float object files, leading to this build failure since GCC is invoked with "-msoft-float" on MIPS:

{standard input}: Warning: .gnu_attribute 4,3 requires `softfloat'
LD arch/mips/alchemy/common/built-in.o
mipsel-softfloat-linux-gnu-ld: Warning: arch/mips/alchemy/common/built-in.o
uses -msoft-float (set by arch/mips/alchemy/common/prom.o), arch/mips/alchemy/common/sleeper.o uses -mhard-float

To fix this, we detect if GAS is new enough to support "-msoft-float" command option, and if it does, we can let GCC pass it to GAS; but then we also need to sprinkle the files which make use of floating point registers with the necessary ".set hardfloat" directives.

---
I've only tested a mips32r1 build, but at least binutils-2.23 and a snapshot from today (with the MIPS fp changes) compile a bootable kernel.

Tests on 64bit and with MSA and other extensions also appreciated!

v3: incorporate Maciej's suggestions:
- detect if gas can handle -msoft-float and ".set hardfloat"
- apply .set hardfloat only where really necessary

v2: cover more files

This was introduced in binutils commit 351cdf24d223290b15fa991e5052ec9e9bd1e284 ("[MIPS] Implement O32 FPXX, FP64 and FP64A ABI extensions").

 arch/mips/Makefile                  |  9 +++++++++
 arch/mips/include/asm/asmmacro-32.h |  5 +++++
 arch/mips/include/asm/asmmacro.h    | 18 ++++++++++++++++++
 arch/mips/include/asm/fpregdef.h    | 14 ++++++++++++++
 arch/mips/include/asm/mipsregs.h    | 19 +++++++++++++++++++
 arch/mips/kernel/genex.S            |  1 +
 arch/mips/kernel/r2300_switch.S     |  5 +++++
 arch/mips/kernel/r4k_fpu.S          |  7 +++++++
 arch/mips/kernel/r4k_switch.S       |  9 +++++++++
 arch/mips/kernel/r6000_fpu.S        |  5 +++++
 10 files changed, 92 insertions(+)
arch/mips/Makefile +9 -0
index bbac51e1..35005e1 100644
@@ -93,6 +93,15 @@ LDFLAGS_vmlinux			+= -G 0 -static -n -nostdlib
 KBUILD_AFLAGS_MODULE		+= -mlong-calls
 KBUILD_CFLAGS_MODULE		+= -mlong-calls
 
+#
+# pass -msoft-float to GAS if it supports it.  However on newer binutils
+# (specifically newer than 2.24.51.20140728) we then also need to explicitly
+# set ".set hardfloat" in all files which manipulate floating point registers.
+#
+ifneq ($(call as-option,-Wa$(comma)-msoft-float,),)
+	cflags-y		+= -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float
+endif
+
 cflags-y += -ffreestanding
 
 #
arch/mips/include/asm/asmmacro-32.h +5 -0
index e38c281..a97ce53 100644
@@ -12,6 +12,9 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
+	.set push
+	SET_HARDFLOAT
+
 	.macro	fpu_save_single thread tmp=t0
 	cfc1	\tmp,  fcr31
 	swc1	$f0,  THREAD_FPR0_LS64(\thread)
@@ -86,6 +89,8 @@
 	ctc1	\tmp, fcr31
 	.endm
 
+	.set pop
+
 	.macro	cpu_save_nonscratch thread
 	LONG_S	s0, THREAD_REG16(\thread)
 	LONG_S	s1, THREAD_REG17(\thread)
arch/mips/include/asm/asmmacro.h +18 -0
index cd9a98b..6caf876 100644
@@ -57,6 +57,8 @@
 #endif /* CONFIG_CPU_MIPSR2 */
 
 	.macro	fpu_save_16even thread tmp=t0
+	.set	push
+	SET_HARDFLOAT
 	cfc1	\tmp, fcr31
 	sdc1	$f0,  THREAD_FPR0_LS64(\thread)
 	sdc1	$f2,  THREAD_FPR2_LS64(\thread)
@@ -75,11 +77,13 @@
 	sdc1	$f28, THREAD_FPR28_LS64(\thread)
 	sdc1	$f30, THREAD_FPR30_LS64(\thread)
 	sw	\tmp, THREAD_FCR31(\thread)
+	.set	pop
 	.endm
 
 	.macro	fpu_save_16odd thread
 	.set	push
 	.set	mips64r2
+	SET_HARDFLOAT
 	sdc1	$f1,  THREAD_FPR1_LS64(\thread)
 	sdc1	$f3,  THREAD_FPR3_LS64(\thread)
 	sdc1	$f5,  THREAD_FPR5_LS64(\thread)
@@ -110,6 +114,8 @@
 	.endm
 
 	.macro	fpu_restore_16even thread tmp=t0
+	.set	push
+	SET_HARDFLOAT
 	lw	\tmp, THREAD_FCR31(\thread)
 	ldc1	$f0,  THREAD_FPR0_LS64(\thread)
 	ldc1	$f2,  THREAD_FPR2_LS64(\thread)
@@ -133,6 +139,7 @@
 	.macro	fpu_restore_16odd thread
 	.set	push
 	.set	mips64r2
+	SET_HARDFLOAT
 	ldc1	$f1,  THREAD_FPR1_LS64(\thread)
 	ldc1	$f3,  THREAD_FPR3_LS64(\thread)
 	ldc1	$f5,  THREAD_FPR5_LS64(\thread)
@@ -277,6 +284,7 @@
 	.macro	cfcmsa	rd, cs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	CFC_MSA_INSN | (\cs << 11)
 	move	\rd, $1
@@ -286,6 +294,7 @@
 	.macro	ctcmsa	cd, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	move	$1, \rs
 	.word	CTC_MSA_INSN | (\cd << 6)
 	.set	pop
@@ -294,6 +303,7 @@
 	.macro	ld_d	wd, off, base
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	add	$1, \base, \off
 	.word	LDD_MSA_INSN | (\wd << 6)
 	.set	pop
@@ -302,6 +312,7 @@
 	.macro	st_d	wd, off, base
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	add	$1, \base, \off
 	.word	STD_MSA_INSN | (\wd << 6)
 	.set	pop
@@ -310,6 +321,7 @@
 	.macro	copy_u_w	rd, ws, n
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	COPY_UW_MSA_INSN | (\n << 16) | (\ws << 11)
 	/* move triggers an assembler bug... */
@@ -320,6 +332,7 @@
 	.macro	copy_u_d	rd, ws, n
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	.insn
 	.word	COPY_UD_MSA_INSN | (\n << 16) | (\ws << 11)
 	/* move triggers an assembler bug... */
@@ -330,6 +343,7 @@
 	.macro	insert_w	wd, n, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	/* move triggers an assembler bug... */
 	or	$1, \rs, zero
 	.word	INSERT_W_MSA_INSN | (\n << 16) | (\wd << 6)
@@ -339,6 +353,7 @@
 	.macro	insert_d	wd, n, rs
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	/* move triggers an assembler bug... */
 	or	$1, \rs, zero
 	.word	INSERT_D_MSA_INSN | (\n << 16) | (\wd << 6)
@@ -381,6 +396,7 @@
 	st_d	31, THREAD_FPR31, \thread
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	cfcmsa	$1, MSA_CSR
 	sw	$1, THREAD_MSA_CSR(\thread)
 	.set	pop
@@ -389,6 +405,7 @@
 	.macro	msa_restore_all	thread
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	lw	$1, THREAD_MSA_CSR(\thread)
 	ctcmsa	MSA_CSR, $1
 	.set	pop
@@ -441,6 +458,7 @@
 	.macro	msa_init_all_upper
 	.set	push
 	.set	noat
+	SET_HARDFLOAT
 	not	$1, zero
 	msa_init_upper	0
 	.set	pop
arch/mips/include/asm/fpregdef.h +14 -0
index 429481f..f184ba0 100644
@@ -14,6 +14,20 @@
 
 #include <asm/sgidefs.h>
 
+/*
+ * starting with binutils 2.24.51.20140729, MIPS binutils warn about mixing
+ * hardfloat and softfloat object files.  The kernel build uses soft-float by
+ * default, so we also need to pass -msoft-float along to GAS if it supports it.
+ * But this in turn causes assembler errors in files which access hardfloat
+ * registers.  We detect if GAS supports "-msoft-float" in the Makefile and
+ * explicitly put ".set hardfloat" where floating point registers are touched.
+ */
+#ifdef GAS_HAS_SET_HARDFLOAT
+#define SET_HARDFLOAT .set hardfloat
+#else
+#define SET_HARDFLOAT
+#endif
+
 #if _MIPS_SIM == _MIPS_SIM_ABI32
 
 /*
arch/mips/include/asm/mipsregs.h +19 -0
index cf3b580..889c012 100644
@@ -1324,6 +1324,7 @@ do {									\
 /*
  * Macros to access the floating point coprocessor control registers
  */
+#ifdef GAS_HAS_SET_HARDFLOAT
 #define read_32bit_cp1_register(source)					\
 ({									\
 	int __res;							\
@@ -1334,11 +1335,29 @@ do {									\
 	"	# gas fails to assemble cfc1 for some archs,	\n"	\
 	"	# like Octeon.					\n"	\
 	"	.set	mips1					\n"	\
+	"	.set	hardfloat				\n"	\
 	"	cfc1	%0,"STR(source)"			\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 	__res;								\
 })
+#else
+#define read_32bit_cp1_register(source)					\
+({									\
+	int __res;							\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	reorder					\n"	\
+	"	# gas fails to assemble cfc1 for some archs,	\n"	\
+	"	# like Octeon.					\n"	\
+	"	.set	mips1					\n"	\
+	"	cfc1	%0,"STR(source)"			\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+	__res;								\
+})
+#endif
 
 #ifdef HAVE_AS_DSP
 #define rddsp(mask)							\
arch/mips/kernel/genex.S +1 -0
index ac35e12..a5e26dd 100644
@@ -358,6 +358,7 @@ NESTED(nmi_handler, PT_SIZE, sp)
 	.set	push
 	/* gas fails to assemble cfc1 for some archs (octeon).*/ \
 	.set	mips1
+	SET_HARDFLOAT
 	cfc1	a1, fcr31
 	li	a2, ~(0x3f << 12)
 	and	a2, a1
arch/mips/kernel/r2300_switch.S +5 -0
index 20b7b04..435ea65 100644
@@ -120,6 +120,9 @@ LEAF(_restore_fp)
 
 #define FPU_DEFAULT  0x00000000
 
+	.set push
+	SET_HARDFLOAT
+
 LEAF(_init_fpu)
 	mfc0	t0, CP0_STATUS
 	li	t1, ST0_CU1
@@ -165,3 +168,5 @@ LEAF(_init_fpu)
 	mtc1	t0, $f31
 	jr	ra
 	END(_init_fpu)
+
+	.set pop
arch/mips/kernel/r4k_fpu.S +7 -0
index 8352523..4a827a3 100644
@@ -21,6 +21,7 @@
 
 	.macro	EX insn, reg, src
 	.set	push
+	SET_HARDFLOAT
 	.set	nomacro
 .ex\@:	\insn	\reg, \src
 	.set	pop
@@ -33,7 +34,10 @@
 	.set	arch=r4000
 
 LEAF(_save_fp_context)
+	.set	push
+	SET_HARDFLOAT
 	cfc1	t1, fcr31
+	.set	pop
 
 #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2)
 	.set	push
@@ -191,7 +195,10 @@ LEAF(_restore_fp_context)
 	EX	ldc1 $f26, SC_FPREGS+208(a0)
 	EX	ldc1 $f28, SC_FPREGS+224(a0)
 	EX	ldc1 $f30, SC_FPREGS+240(a0)
+	.set push
+	SET_HARDFLOAT
 	ctc1	t1, fcr31
+	.set pop
 	jr	ra
 	 li	v0, 0					# success
 	END(_restore_fp_context)
arch/mips/kernel/r4k_switch.S +9 -0
index 4c4ec18..6467a8b 100644
@@ -65,8 +65,12 @@
 	bgtz	a3, 1f
 
 	/* Save 128b MSA vector context + scalar FP control & status. */
+	.set push
+	SET_HARDFLOAT
 	cfc1	t1, fcr31
 	msa_save_all	a0
+	.set pop	/* SET_HARDFLOAT */
+
 	sw	t1, THREAD_FCR31(a0)
 	b	2f
 
@@ -161,6 +165,9 @@ LEAF(_init_msa_upper)
 
 #define FPU_DEFAULT  0x00000000
 
+	.set push
+	SET_HARDFLOAT
+
 LEAF(_init_fpu)
 	mfc0	t0, CP0_STATUS
 	li	t1, ST0_CU1
@@ -291,3 +298,5 @@ LEAF(_init_fpu)
 #endif
 	jr	ra
 	END(_init_fpu)
+
+	.set pop	/* SET_HARDFLOAT */
arch/mips/kernel/r6000_fpu.S +5 -1
index da0fbe4..4707738 100644
@@ -18,6 +18,9 @@
 
 	.set	noreorder
 	.set	mips2
+	.set	push
+	SET_HARDFLOAT
+
 	/* Save floating point context */
 	LEAF(_save_fp_context)
 	mfc0	t0,CP0_STATUS
@@ -85,3 +88,5 @@
 1:	jr	ra
 	 nop
 	END(_restore_fp_context)
+
+	.set pop	/* SET_HARDFLOAT */
--

2.1.2

Signature · 1 line
markos
#4 lore raw
Quoted 24 lines · Markos Chandras

(top posting so Matthew can see the entire patch)

+CC Matthew Fortune who has some comments on the patch.

Review

Quoted 1 line · Manuel Lauss
(quoted diff) +0 -0

b/arch/mips/include/asm/asmmacro-32.h

Quoted 17 lines

index e38c281..a97ce53 100644

arch/mips/include/asm/asmmacro-32.h +3 -0
@@ -12,6 +12,9 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
+	.set push
+	SET_HARDFLOAT
+
 	.macro	fpu_save_single thread tmp=t0
 	cfc1	\tmp,  fcr31
 	swc1	$f0,  THREAD_FPR0_LS64(\thread)
@@ -86,6 +89,8 @@
 	ctc1	\tmp, fcr31
 	.endm
 
Quoted 2 lines

arch/mips/include/asm/asmmacro-32.h line 93

Quoted 2 lines
arch/mips/include/asm/asmmacro-32.h +2 -0
+	.set pop
+

Any reason for putting the push/pop outside of the macro here but inside the macros elsewhere?

Quoted 34 lines

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/mips/include/asm/mipsregs.h

arch/mips/include/asm/mipsregs.h do {

Quoted 4 lines

index cf3b580..889c012 100644

arch/mips/include/asm/mipsregs.h +0 -0
@@ -1324,6 +1324,7 @@ do {
	\

arch/mips/include/asm/mipsregs.h do {

Quoted 8 lines
arch/mips/include/asm/mipsregs.h +1 -0
 /*
  * Macros to access the floating point coprocessor control registers
  */
+#ifdef GAS_HAS_SET_HARDFLOAT
 #define read_32bit_cp1_register(source)					\
 ({									\
 	int __res;							\
@@ -1334,11 +1335,29 @@ do {
		\
Quoted 18 lines
arch/mips/include/asm/mipsregs.h +10 -0
 	"	# gas fails to assemble cfc1 for some archs,	\n"	\
 	"	# like Octeon.					\n"	\
 	"	.set	mips1					\n"	\
+	"	.set	hardfloat				\n"	\
 	"	cfc1	%0,"STR(source)"			\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 	__res;								\
 })
+#else
+#define read_32bit_cp1_register(source)					\
+({									\
+	int __res;							\
+									\
+	__asm__ __volatile__(						\
+	"	.set	push					\n"	\
+	"	.set	reorder					\n"	\
+	"	# gas fails to assemble cfc1 for some archs,	\n"	\
Quoted 8 lines

arch/mips/include/asm/mipsregs.h do { \ · line 1360

Quoted 8 lines
arch/mips/include/asm/mipsregs.h +8 -0
+	"	# like Octeon.					\n"	\
+	"	.set	mips1					\n"	\
+	"	cfc1	%0,"STR(source)"			\n"	\
+	"	.set	pop					\n"	\
+	: "=r" (__res));						\
+	__res;								\
+})
+#endif

This looks fairly ugly. I believe you can just add the hardfloat using:

Quoted 8 lines

arch/mips/include/asm/mipsregs.h do { \ · line 1342

Quoted 8 lines
arch/mips/include/asm/mipsregs.h +1 -0
 	"	# gas fails to assemble cfc1 for some archs,	\n"	\
 	"	# like Octeon.					\n"	\
 	"	.set	mips1					\n"	\
+	"	"STR(SET_HARDFLOAT)"			\n"	\
 	"	cfc1	%0,"STR(source)"			\n"	\
 	"	.set	pop					\n"	\
 	: "=r" (__res));						\
 	__res;								\

The ctc1/cfc1 instructions are quite unusual as they were (before my binutils patch) floating point instructions but are general purpose after the patch. While that may indicate that you don't need .set hardfloat to use ctc1/cfc1 that is not true when you consider using a new compiler and/or the -Wa,-msoft-float CFLAGS patch with an old assembler. It would therefore be wise to test the kernel patch with an assembler which pre-dates my FPXX patch to make sure that all instances of ctc1/cfc1 have been caught.

That is the reason why Markos saw issues with using one of the mentor toolchains with your patch in place.

Markos' secondary issue relating to odd-numbered single-precision registers is probably something to address on the GCC side but I haven't quite figured out what the root cause is. I'm trying to avoid the kernel having to add both .set hardfloat and .set oddspreg as I think it is legitimate for the kernel to expect that when enabling hardfloat in a softfloat module then the standard hardfloat ABI should apply to that region and all registers should be available.

Hope that is helpful,

Matthew

#5 lore raw
Quoted 25 lines · Matthew Fortune
Quoted 24 lines · Markos Chandras

(top posting so Matthew can see the entire patch)

+CC Matthew Fortune who has some comments on the patch.

Review

Quoted 1 line · Manuel Lauss
(quoted diff) +0 -0

b/arch/mips/include/asm/asmmacro-32.h

Quoted 17 lines

index e38c281..a97ce53 100644

arch/mips/include/asm/asmmacro-32.h +3 -0
@@ -12,6 +12,9 @@
 #include <asm/fpregdef.h>
 #include <asm/mipsregs.h>
 
+   .set push
+   SET_HARDFLOAT
+
    .macro  fpu_save_single thread tmp=t0
    cfc1    \tmp,  fcr31
    swc1    $f0,  THREAD_FPR0_LS64(\thread)
@@ -86,6 +89,8 @@
    ctc1    \tmp, fcr31
    .endm
 
Quoted 5 lines
Quoted 2 lines

arch/mips/include/asm/asmmacro-32.h line 93

Quoted 2 lines
arch/mips/include/asm/asmmacro-32.h +2 -0
+   .set pop
+

Any reason for putting the push/pop outside of the macro here but inside the macros elsewhere?

I think I figured I just enclose all float-using macros with this in one go. I'll fix it.

Quoted 36 lines
Quoted 36 lines

Review

Quoted 1 line
(quoted diff) +0 -0

b/arch/mips/include/asm/mipsregs.h

arch/mips/include/asm/mipsregs.h do {

Quoted 4 lines

index cf3b580..889c012 100644

arch/mips/include/asm/mipsregs.h +0 -0
@@ -1324,6 +1324,7 @@ do {
      \

arch/mips/include/asm/mipsregs.h do {

Quoted 8 lines
arch/mips/include/asm/mipsregs.h +1 -0
 /*
  * Macros to access the floating point coprocessor control registers
  */
+#ifdef GAS_HAS_SET_HARDFLOAT
 #define read_32bit_cp1_register(source)                                    \
 ({                                                                 \
    int __res;                                                      \
@@ -1334,11 +1335,29 @@ do {
              \
Quoted 20 lines
arch/mips/include/asm/mipsregs.h +12 -0
    "       # gas fails to assemble cfc1 for some archs,    \n"     \
    "       # like Octeon.                                  \n"     \
    "       .set    mips1                                   \n"     \
+   "       .set    hardfloat                               \n"     \
    "       cfc1    %0,"STR(source)"                        \n"     \
    "       .set    pop                                     \n"     \
    : "=r" (__res));                                                \
    __res;                                                          \
 })
+#else
+#define read_32bit_cp1_register(source)                                    \
+({                                                                 \
+   int __res;                                                      \
+                                                                   \
+   __asm__ __volatile__(                                           \
+   "       .set    push                                    \n"     \
+   "       .set    reorder                                 \n"     \
+   "       # gas fails to assemble cfc1 for some archs,    \n"     \
+   "       # like Octeon.                                  \n"     \
+   "       .set    mips1                                   \n"     \
Quoted 17 lines
Quoted 6 lines

arch/mips/include/asm/mipsregs.h do { \ · line 1360

Quoted 6 lines
arch/mips/include/asm/mipsregs.h +6 -0
+   "       cfc1    %0,"STR(source)"                        \n"     \
+   "       .set    pop                                     \n"     \
+   : "=r" (__res));                                                \
+   __res;                                                          \
+})
+#endif

This looks fairly ugly. I believe you can just add the hardfloat using:

Quoted 8 lines
Quoted 8 lines
arch/mips/include/asm/mipsregs.h +1 -0
    "       # gas fails to assemble cfc1 for some archs,    \n"     \
    "       # like Octeon.                                  \n"     \
    "       .set    mips1                                   \n"     \
+   "       "STR(SET_HARDFLOAT)"                    \n"     \
    "       cfc1    %0,"STR(source)"                        \n"     \
    "       .set    pop                                     \n"     \
    : "=r" (__res));                                                \
    __res;                                                          \

I didn't know that, thanks!

Quoted 7 lines

The ctc1/cfc1 instructions are quite unusual as they were (before my binutils patch) floating point instructions but are general purpose after the patch. While that may indicate that you don't need .set hardfloat to use ctc1/cfc1 that is not true when you consider using a new compiler and/or the -Wa,-msoft-float CFLAGS patch with an old assembler. It would therefore be wise to test the kernel patch with an assembler which pre-dates my FPXX patch to make sure that all instances of ctc1/cfc1 have been caught.

Actually, I did test the patch with 2.24 first, but just with my mips32r1 alchemy target. I'll try to fix everything, retest and resend.

Thank you,
Manuel