diff -Nur linux-3.14.67.orig/arch/mips/include/asm/asmmacro-32.h linux-3.14.67/arch/mips/include/asm/asmmacro-32.h --- linux-3.14.67.orig/arch/mips/include/asm/asmmacro-32.h 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/include/asm/asmmacro-32.h 2016-04-27 16:18:41.729238756 +0200 @@ -13,6 +13,8 @@ #include .macro fpu_save_single thread tmp=t0 + .set push + SET_HARDFLOAT cfc1 \tmp, fcr31 swc1 $f0, THREAD_FPR0(\thread) swc1 $f1, THREAD_FPR1(\thread) @@ -47,9 +49,12 @@ swc1 $f30, THREAD_FPR30(\thread) swc1 $f31, THREAD_FPR31(\thread) sw \tmp, THREAD_FCR31(\thread) + .set pop .endm .macro fpu_restore_single thread tmp=t0 + .set push + SET_HARDFLOAT lw \tmp, THREAD_FCR31(\thread) lwc1 $f0, THREAD_FPR0(\thread) lwc1 $f1, THREAD_FPR1(\thread) @@ -84,6 +89,7 @@ lwc1 $f30, THREAD_FPR30(\thread) lwc1 $f31, THREAD_FPR31(\thread) ctc1 \tmp, fcr31 + .set pop .endm .macro cpu_save_nonscratch thread diff -Nur linux-3.14.67.orig/arch/mips/include/asm/asmmacro.h linux-3.14.67/arch/mips/include/asm/asmmacro.h --- linux-3.14.67.orig/arch/mips/include/asm/asmmacro.h 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/include/asm/asmmacro.h 2016-04-27 16:18:41.729238756 +0200 @@ -74,6 +74,8 @@ #endif /* CONFIG_MIPS_MT_SMTC */ .macro fpu_save_16even thread tmp=t0 + .set push + SET_HARDFLOAT cfc1 \tmp, fcr31 sdc1 $f0, THREAD_FPR0(\thread) sdc1 $f2, THREAD_FPR2(\thread) @@ -127,6 +129,8 @@ .endm .macro fpu_restore_16even thread tmp=t0 + .set push + SET_HARDFLOAT lw \tmp, THREAD_FCR31(\thread) ldc1 $f0, THREAD_FPR0(\thread) ldc1 $f2, THREAD_FPR2(\thread) diff -Nur linux-3.14.67.orig/arch/mips/include/asm/fpregdef.h linux-3.14.67/arch/mips/include/asm/fpregdef.h --- linux-3.14.67.orig/arch/mips/include/asm/fpregdef.h 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/include/asm/fpregdef.h 2016-04-27 16:18:41.729238756 +0200 @@ -14,6 +14,20 @@ #include +/* + * 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 /* diff -Nur linux-3.14.67.orig/arch/mips/include/asm/mipsregs.h linux-3.14.67/arch/mips/include/asm/mipsregs.h --- linux-3.14.67.orig/arch/mips/include/asm/mipsregs.h 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/include/asm/mipsregs.h 2016-04-27 16:18:41.729238756 +0200 @@ -1251,7 +1251,7 @@ /* * Macros to access the floating point coprocessor control registers */ -#define read_32bit_cp1_register(source) \ +#define _read_32bit_cp1_register(source, gas_hardfloat) \ ({ \ int __res; \ \ @@ -1261,12 +1261,21 @@ " # gas fails to assemble cfc1 for some archs, \n" \ " # like Octeon. \n" \ " .set mips1 \n" \ + " "STR(gas_hardfloat)" \n" \ " cfc1 %0,"STR(source)" \n" \ " .set pop \n" \ : "=r" (__res)); \ __res; \ }) +#ifdef GAS_HAS_SET_HARDFLOAT +#define read_32bit_cp1_register(source) \ + _read_32bit_cp1_register(source, .set hardfloat) +#else +#define read_32bit_cp1_register(source) \ + _read_32bit_cp1_register(source, ) +#endif + #ifdef HAVE_AS_DSP #define rddsp(mask) \ ({ \ diff -Nur linux-3.14.67.orig/arch/mips/kernel/genex.S linux-3.14.67/arch/mips/kernel/genex.S --- linux-3.14.67.orig/arch/mips/kernel/genex.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/genex.S 2016-04-27 16:18:41.729238756 +0200 @@ -408,6 +408,7 @@ .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 diff -Nur linux-3.14.67.orig/arch/mips/kernel/r2300_fpu.S linux-3.14.67/arch/mips/kernel/r2300_fpu.S --- linux-3.14.67.orig/arch/mips/kernel/r2300_fpu.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/r2300_fpu.S 2016-04-27 16:18:41.729238756 +0200 @@ -28,6 +28,8 @@ .set mips1 /* Save floating point context */ LEAF(_save_fp_context) + .set push + SET_HARDFLOAT li v0, 0 # assume success cfc1 t1,fcr31 EX(swc1 $f0,(SC_FPREGS+0)(a0)) @@ -65,6 +67,7 @@ EX(sw t1,(SC_FPC_CSR)(a0)) cfc1 t0,$0 # implementation/version jr ra + .set pop .set nomacro EX(sw t0,(SC_FPC_EIR)(a0)) .set macro @@ -80,6 +83,8 @@ * stack frame which might have been changed by the user. */ LEAF(_restore_fp_context) + .set push + SET_HARDFLOAT li v0, 0 # assume success EX(lw t0,(SC_FPC_CSR)(a0)) EX(lwc1 $f0,(SC_FPREGS+0)(a0)) @@ -116,6 +121,7 @@ EX(lwc1 $f31,(SC_FPREGS+248)(a0)) jr ra ctc1 t0,fcr31 + .set pop END(_restore_fp_context) .set reorder diff -Nur linux-3.14.67.orig/arch/mips/kernel/r2300_switch.S linux-3.14.67/arch/mips/kernel/r2300_switch.S --- linux-3.14.67.orig/arch/mips/kernel/r2300_switch.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/r2300_switch.S 2016-04-27 16:18:41.729238756 +0200 @@ -120,6 +120,9 @@ #define FPU_DEFAULT 0x00000000 + .set push + SET_HARDFLOAT + LEAF(_init_fpu) mfc0 t0, CP0_STATUS li t1, ST0_CU1 @@ -165,3 +168,5 @@ mtc1 t0, $f31 jr ra END(_init_fpu) + + .set pop diff -Nur linux-3.14.67.orig/arch/mips/kernel/r4k_fpu.S linux-3.14.67/arch/mips/kernel/r4k_fpu.S --- linux-3.14.67.orig/arch/mips/kernel/r4k_fpu.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/r4k_fpu.S 2016-04-27 16:18:41.729238756 +0200 @@ -19,8 +19,12 @@ #include #include +/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ +#undef fp + .macro EX insn, reg, src .set push + SET_HARDFLOAT .set nomacro .ex\@: \insn \reg, \src .set pop @@ -33,12 +37,17 @@ .set mips3 LEAF(_save_fp_context) + .set push + SET_HARDFLOAT cfc1 t1, fcr31 + .set pop #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) .set push + SET_HARDFLOAT #ifdef CONFIG_CPU_MIPS32_R2 - .set mips64r2 + .set mips32r2 + .set fp=64 mfc0 t0, CP0_STATUS sll t0, t0, 5 bgez t0, 1f # skip storing odd if FR=0 @@ -64,6 +73,8 @@ 1: .set pop #endif + .set push + SET_HARDFLOAT /* Store the 16 even double precision registers */ EX sdc1 $f0, SC_FPREGS+0(a0) EX sdc1 $f2, SC_FPREGS+16(a0) @@ -84,11 +95,14 @@ EX sw t1, SC_FPC_CSR(a0) jr ra li v0, 0 # success + .set pop END(_save_fp_context) #ifdef CONFIG_MIPS32_COMPAT /* Save 32-bit process floating point context */ LEAF(_save_fp_context32) + .set push + SET_HARDFLOAT cfc1 t1, fcr31 mfc0 t0, CP0_STATUS @@ -134,6 +148,7 @@ EX sw t1, SC32_FPC_CSR(a0) cfc1 t0, $0 # implementation/version EX sw t0, SC32_FPC_EIR(a0) + .set pop jr ra li v0, 0 # success @@ -150,8 +165,10 @@ #if defined(CONFIG_64BIT) || defined(CONFIG_CPU_MIPS32_R2) .set push + SET_HARDFLOAT #ifdef CONFIG_CPU_MIPS32_R2 - .set mips64r2 + .set mips32r2 + .set fp=64 mfc0 t0, CP0_STATUS sll t0, t0, 5 bgez t0, 1f # skip loading odd if FR=0 @@ -175,6 +192,8 @@ EX ldc1 $f31, SC_FPREGS+248(a0) 1: .set pop #endif + .set push + SET_HARDFLOAT EX ldc1 $f0, SC_FPREGS+0(a0) EX ldc1 $f2, SC_FPREGS+16(a0) EX ldc1 $f4, SC_FPREGS+32(a0) @@ -192,6 +211,7 @@ EX ldc1 $f28, SC_FPREGS+224(a0) EX ldc1 $f30, SC_FPREGS+240(a0) ctc1 t1, fcr31 + .set pop jr ra li v0, 0 # success END(_restore_fp_context) @@ -199,6 +219,8 @@ #ifdef CONFIG_MIPS32_COMPAT LEAF(_restore_fp_context32) /* Restore an o32 sigcontext. */ + .set push + SET_HARDFLOAT EX lw t1, SC32_FPC_CSR(a0) mfc0 t0, CP0_STATUS @@ -242,6 +264,7 @@ ctc1 t1, fcr31 jr ra li v0, 0 # success + .set pop END(_restore_fp_context32) #endif diff -Nur linux-3.14.67.orig/arch/mips/kernel/r4k_switch.S linux-3.14.67/arch/mips/kernel/r4k_switch.S --- linux-3.14.67.orig/arch/mips/kernel/r4k_switch.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/r4k_switch.S 2016-04-27 16:18:41.729238756 +0200 @@ -22,6 +22,9 @@ #include +/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */ +#undef fp + /* * Offset to the current process status flags, the first 32 bytes of the * stack are not used. @@ -151,6 +154,9 @@ #define FPU_DEFAULT 0x00000000 + .set push + SET_HARDFLOAT + LEAF(_init_fpu) #ifdef CONFIG_MIPS_MT_SMTC /* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */ @@ -231,7 +237,8 @@ #ifdef CONFIG_CPU_MIPS32_R2 .set push - .set mips64r2 + .set mips32r2 + .set fp=64 sll t0, t0, 5 # is Status.FR set? bgez t0, 1f # no: skip setting upper 32b @@ -290,3 +297,5 @@ #endif jr ra END(_init_fpu) + + .set pop /* SET_HARDFLOAT */ diff -Nur linux-3.14.67.orig/arch/mips/kernel/r6000_fpu.S linux-3.14.67/arch/mips/kernel/r6000_fpu.S --- linux-3.14.67.orig/arch/mips/kernel/r6000_fpu.S 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/kernel/r6000_fpu.S 2016-04-27 16:18:41.729238756 +0200 @@ -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 */ diff -Nur linux-3.14.67.orig/arch/mips/Makefile linux-3.14.67/arch/mips/Makefile --- linux-3.14.67.orig/arch/mips/Makefile 2016-04-20 08:41:04.000000000 +0200 +++ linux-3.14.67/arch/mips/Makefile 2016-04-27 16:18:41.729238756 +0200 @@ -93,6 +93,15 @@ 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 #