You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

521 lines
13 KiB

diff --git a/arch/mips/Makefile b/arch/mips/Makefile
index 6f7978f..446a039 100644
--- a/arch/mips/Makefile
+++ b/arch/mips/Makefile
@@ -57,6 +57,15 @@ ifdef CONFIG_FUNCTION_GRAPH_TRACER
endif
cflags-y += $(call cc-option, -mno-check-zero-division)
+GCC_VERSION = 60000 # $(shell ../../cross/mips/bcm7335/bin/mipsel-unknown-linux-gcc --version | grep ^mipsel-unknown-linux-gcc | sed 's/^.* //g' | sed -e 's/\.\([0-9][0-9]\)/\1/g' -e 's/\.\([0-9]\)/0\1/g' -e 's/^[0-9]\{3,4\}$$/&00/')
+GCC_GTEQ_493 = $(shell expr $(GCC_VERSION) \>= 40903)
+ifeq ($(GCC_GTEQ_493),1)
+ # oskwon fixed.
+ ifneq ($(call as-option,-Wa$(comma)-msoft-float,),)
+ cflags-y += -DGAS_HAS_SET_HARDFLOAT -Wa,-msoft-float
+ endif
+endif
+
ifdef CONFIG_32BIT
ld-emul = $(32bit-emul)
vmlinux-32 = vmlinux
diff --git a/arch/mips/brcmstb/vector.S b/arch/mips/brcmstb/vector.S
index 6eab27b..12c36e2 100644
--- a/arch/mips/brcmstb/vector.S
+++ b/arch/mips/brcmstb/vector.S
@@ -27,10 +27,19 @@
#include <asm/brcmstb/brcmstb.h>
.macro CLR_FPR a b c d
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
mtc1 $0, $\a
mtc1 $0, $\b
mtc1 $0, $\c
mtc1 $0, $\d
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.endm
.macro BARRIER
diff --git a/arch/mips/include/asm/asmmacro-32.h b/arch/mips/include/asm/asmmacro-32.h
index 2413afe..7ac5413 100644
--- a/arch/mips/include/asm/asmmacro-32.h
+++ b/arch/mips/include/asm/asmmacro-32.h
@@ -13,6 +13,11 @@
#include <asm/mipsregs.h>
.macro fpu_save_double thread status tmp1=t0
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
cfc1 \tmp1, fcr31
sdc1 $f0, THREAD_FPR0(\thread)
sdc1 $f2, THREAD_FPR2(\thread)
@@ -31,9 +36,18 @@
sdc1 $f28, THREAD_FPR28(\thread)
sdc1 $f30, THREAD_FPR30(\thread)
sw \tmp1, THREAD_FCR31(\thread)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.endm
.macro fpu_save_single thread tmp=t0
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
cfc1 \tmp, fcr31
swc1 $f0, THREAD_FPR0(\thread)
swc1 $f1, THREAD_FPR1(\thread)
@@ -68,9 +82,18 @@
swc1 $f30, THREAD_FPR30(\thread)
swc1 $f31, THREAD_FPR31(\thread)
sw \tmp, THREAD_FCR31(\thread)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.endm
.macro fpu_restore_double thread status tmp=t0
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
lw \tmp, THREAD_FCR31(\thread)
ldc1 $f0, THREAD_FPR0(\thread)
ldc1 $f2, THREAD_FPR2(\thread)
@@ -89,9 +112,18 @@
ldc1 $f28, THREAD_FPR28(\thread)
ldc1 $f30, THREAD_FPR30(\thread)
ctc1 \tmp, fcr31
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.endm
.macro fpu_restore_single thread tmp=t0
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
lw \tmp, THREAD_FCR31(\thread)
lwc1 $f0, THREAD_FPR0(\thread)
lwc1 $f1, THREAD_FPR1(\thread)
@@ -126,9 +158,18 @@
lwc1 $f30, THREAD_FPR30(\thread)
lwc1 $f31, THREAD_FPR31(\thread)
ctc1 \tmp, fcr31
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.endm
.macro cpu_save_nonscratch thread
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
LONG_S s0, THREAD_REG16(\thread)
LONG_S s1, THREAD_REG17(\thread)
LONG_S s2, THREAD_REG18(\thread)
@@ -142,6 +183,11 @@
.endm
.macro cpu_restore_nonscratch thread
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
LONG_L s0, THREAD_REG16(\thread)
LONG_L s1, THREAD_REG17(\thread)
LONG_L s2, THREAD_REG18(\thread)
diff --git a/arch/mips/include/asm/fpregdef.h b/arch/mips/include/asm/fpregdef.h
index 429481f..6396e21 100644
--- a/arch/mips/include/asm/fpregdef.h
+++ b/arch/mips/include/asm/fpregdef.h
@@ -14,6 +14,25 @@
#include <asm/sgidefs.h>
+#define GCC_VERSION (__GNUC__ * 10000 \
+ + __GNUC_MINOR__ * 100 \
+ + __GNUC_PATCHLEVEL__)
+
+/*oskwon fixed.*/
+/*
+ * 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 --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h
index 0da44d4..f338747 100644
--- a/arch/mips/include/asm/mipsregs.h
+++ b/arch/mips/include/asm/mipsregs.h
@@ -1144,7 +1144,7 @@ do { \
/*
* 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; \
\
@@ -1154,11 +1154,19 @@ do { \
" # 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 --git a/arch/mips/kernel/branch.c b/arch/mips/kernel/branch.c
index 83ffe95..920168b 100644
--- a/arch/mips/kernel/branch.c
+++ b/arch/mips/kernel/branch.c
@@ -188,7 +188,12 @@ int __compute_return_epc_for_insn(struct pt_regs *regs,
case cop1_op:
preempt_disable();
if (is_fpu_owner())
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ fcr31 = read_32bit_cp1_register(CP1_STATUS); /*oskwon*/
+#else
asm volatile("cfc1\t%0,$31" : "=r" (fcr31));
+#endif
else
fcr31 = current->thread.fpu.fcr31;
preempt_enable();
diff --git a/arch/mips/kernel/genex.S b/arch/mips/kernel/genex.S
index bcd9a7c..bc09cf5 100644
--- a/arch/mips/kernel/genex.S
+++ b/arch/mips/kernel/genex.S
@@ -387,6 +387,10 @@ NESTED(nmi_handler, PT_SIZE, sp)
.set push
/* gas fails to assemble cfc1 for some archs (octeon).*/ \
.set mips1
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ SET_HARDFLOAT
+#endif
cfc1 a1, fcr31
li a2, ~(0x3f << 12)
and a2, a1
diff --git a/arch/mips/kernel/r2300_fpu.S b/arch/mips/kernel/r2300_fpu.S
index f31063d..d2520ca 100644
--- a/arch/mips/kernel/r2300_fpu.S
+++ b/arch/mips/kernel/r2300_fpu.S
@@ -28,6 +28,11 @@
.set mips1
/* Save floating point context */
LEAF(_save_fp_context)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
li v0, 0 # assume success
cfc1 t1,fcr31
EX(swc1 $f0,(SC_FPREGS+0)(a0))
@@ -65,6 +70,10 @@ LEAF(_save_fp_context)
EX(sw t1,(SC_FPC_CSR)(a0))
cfc1 t0,$0 # implementation/version
jr ra
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
.set nomacro
EX(sw t0,(SC_FPC_EIR)(a0))
.set macro
@@ -80,6 +89,11 @@ LEAF(_save_fp_context)
* stack frame which might have been changed by the user.
*/
LEAF(_restore_fp_context)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
li v0, 0 # assume success
EX(lw t0,(SC_FPC_CSR)(a0))
EX(lwc1 $f0,(SC_FPREGS+0)(a0))
@@ -116,6 +130,10 @@ LEAF(_restore_fp_context)
EX(lwc1 $f31,(SC_FPREGS+248)(a0))
jr ra
ctc1 t0,fcr31
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
END(_restore_fp_context)
.set reorder
diff --git a/arch/mips/kernel/r2300_switch.S b/arch/mips/kernel/r2300_switch.S
index 5266c6e..4bd0684 100644
--- a/arch/mips/kernel/r2300_switch.S
+++ b/arch/mips/kernel/r2300_switch.S
@@ -113,6 +113,12 @@ LEAF(_restore_fp)
#define FPU_DEFAULT 0x00000000
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
+
LEAF(_init_fpu)
mfc0 t0, CP0_STATUS
li t1, ST0_CU1
@@ -158,3 +164,9 @@ LEAF(_init_fpu)
mtc1 t0, $f31
jr ra
END(_init_fpu)
+
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
+
diff --git a/arch/mips/kernel/r4k_fpu.S b/arch/mips/kernel/r4k_fpu.S
index 55ffe14..485e915 100644
--- a/arch/mips/kernel/r4k_fpu.S
+++ b/arch/mips/kernel/r4k_fpu.S
@@ -19,8 +19,18 @@
#include <asm/asm-offsets.h>
#include <asm/regdef.h>
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
+#undef fp
+#endif
+
.macro EX insn, reg, src
.set push
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ SET_HARDFLOAT
+#endif
.set nomacro
.ex\@: \insn \reg, \src
.set pop
@@ -33,7 +43,16 @@
.set mips3
LEAF(_save_fp_context)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
cfc1 t1, fcr31
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
#ifdef CONFIG_64BIT
/* Store the 16 odd double precision registers */
@@ -54,8 +73,12 @@ LEAF(_save_fp_context)
EX sdc1 $f29, SC_FPREGS+232(a0)
EX sdc1 $f31, SC_FPREGS+248(a0)
#endif
-
/* Store the 16 even double precision registers */
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
EX sdc1 $f0, SC_FPREGS+0(a0)
EX sdc1 $f2, SC_FPREGS+16(a0)
EX sdc1 $f4, SC_FPREGS+32(a0)
@@ -75,11 +98,20 @@ LEAF(_save_fp_context)
EX sw t1, SC_FPC_CSR(a0)
jr ra
li v0, 0 # success
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
END(_save_fp_context)
#ifdef CONFIG_MIPS32_COMPAT
/* Save 32-bit process floating point context */
LEAF(_save_fp_context32)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
cfc1 t1, fcr31
EX sdc1 $f0, SC32_FPREGS+0(a0)
@@ -101,6 +133,10 @@ LEAF(_save_fp_context32)
EX sw t1, SC32_FPC_CSR(a0)
cfc1 t0, $0 # implementation/version
EX sw t0, SC32_FPC_EIR(a0)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
jr ra
li v0, 0 # success
@@ -132,6 +168,12 @@ LEAF(_restore_fp_context)
EX ldc1 $f29, SC_FPREGS+232(a0)
EX ldc1 $f31, SC_FPREGS+248(a0)
#endif
+
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
EX ldc1 $f0, SC_FPREGS+0(a0)
EX ldc1 $f2, SC_FPREGS+16(a0)
EX ldc1 $f4, SC_FPREGS+32(a0)
@@ -149,6 +191,10 @@ LEAF(_restore_fp_context)
EX ldc1 $f28, SC_FPREGS+224(a0)
EX ldc1 $f30, SC_FPREGS+240(a0)
ctc1 t0, fcr31
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
jr ra
li v0, 0 # success
END(_restore_fp_context)
@@ -156,6 +202,11 @@ LEAF(_restore_fp_context)
#ifdef CONFIG_MIPS32_COMPAT
LEAF(_restore_fp_context32)
/* Restore an o32 sigcontext. */
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
EX lw t0, SC32_FPC_CSR(a0)
EX ldc1 $f0, SC32_FPREGS+0(a0)
EX ldc1 $f2, SC32_FPREGS+16(a0)
@@ -176,6 +227,10 @@ LEAF(_restore_fp_context32)
ctc1 t0, fcr31
jr ra
li v0, 0 # success
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop
+#endif
END(_restore_fp_context32)
#endif
diff --git a/arch/mips/kernel/r4k_switch.S b/arch/mips/kernel/r4k_switch.S
index 5e51219..1c5bc5c 100644
--- a/arch/mips/kernel/r4k_switch.S
+++ b/arch/mips/kernel/r4k_switch.S
@@ -22,6 +22,12 @@
#include <asm/asmmacro.h>
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+/* preprocessor replaces the fp in ".set fp=64" with $30 otherwise */
+#undef fp
+#endif
+
/*
* Offset to the current process status flags, the first 32 bytes of the
* stack are not used.
@@ -145,6 +151,12 @@ LEAF(_restore_fp)
#define FPU_DEFAULT 0x00000000
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
+
LEAF(_init_fpu)
#ifdef CONFIG_MIPS_MT_SMTC
/* Rather than manipulate per-VPE Status, set per-TC bit in TCStatus */
@@ -243,3 +255,9 @@ LEAF(_init_fpu)
#endif
jr ra
END(_init_fpu)
+
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop /* SET_HARDFLOAT */
+#endif
+
diff --git a/arch/mips/kernel/r6000_fpu.S b/arch/mips/kernel/r6000_fpu.S
index da0fbe4..4299891 100644
--- a/arch/mips/kernel/r6000_fpu.S
+++ b/arch/mips/kernel/r6000_fpu.S
@@ -18,6 +18,11 @@
.set noreorder
.set mips2
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set push
+ SET_HARDFLOAT
+#endif
/* Save floating point context */
LEAF(_save_fp_context)
mfc0 t0,CP0_STATUS
@@ -48,6 +53,10 @@
1: jr ra
nop
END(_save_fp_context)
+/* Test for GCC >= 4.9.3 */
+#if GCC_VERSION >= 40903
+ .set pop /* SET_HARDFLOAT */
+#endif
/* Restore FPU state:
* - fp gp registers