Commit 93adeaf6 authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by Ralf Baechle

MIPS: Determine the presence of IEEE Std 754-2008 features

Determine the presence of and the amount of control available over IEEE
Std 754-2008 features.

In the case of a hardware FPU being used examine the FIR register for
the presence of the HAS2008 bit and then the FCSR register for the
writability of the ABS2008 and NAN2008 bits and the hardwired state of
each of these bits if read-only.  Update the initial FCSR contents used
for threads and the FCSR writability mask accordingly.

For full FPU emulation and MIPS32 or MIPS64 processors make the FCSR
ABS2008 and NAN2008 bits writable.
Signed-off-by: default avatarMaciej W. Rozycki <macro@imgtec.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Matthew Fortune <Matthew.Fortune@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/11480/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 2b5e869e
...@@ -98,6 +98,78 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c) ...@@ -98,6 +98,78 @@ static inline void cpu_set_fpu_fcsr_mask(struct cpuinfo_mips *c)
c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask; c->fpu_msk31 = ~(fcsr0 ^ fcsr1) & ~mask;
} }
/*
* Determine the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes
* supported by FPU hardware.
*/
static void cpu_set_fpu_2008(struct cpuinfo_mips *c)
{
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
unsigned long sr, fir, fcsr, fcsr0, fcsr1;
sr = read_c0_status();
__enable_fpu(FPU_AS_IS);
fir = read_32bit_cp1_register(CP1_REVISION);
if (fir & MIPS_FPIR_HAS2008) {
fcsr = read_32bit_cp1_register(CP1_STATUS);
fcsr0 = fcsr & ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
write_32bit_cp1_register(CP1_STATUS, fcsr0);
fcsr0 = read_32bit_cp1_register(CP1_STATUS);
fcsr1 = fcsr | FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
write_32bit_cp1_register(CP1_STATUS, fcsr1);
fcsr1 = read_32bit_cp1_register(CP1_STATUS);
write_32bit_cp1_register(CP1_STATUS, fcsr);
if (!(fcsr0 & FPU_CSR_NAN2008))
c->options |= MIPS_CPU_NAN_LEGACY;
if (fcsr1 & FPU_CSR_NAN2008)
c->options |= MIPS_CPU_NAN_2008;
if ((fcsr0 ^ fcsr1) & FPU_CSR_ABS2008)
c->fpu_msk31 &= ~FPU_CSR_ABS2008;
else
c->fpu_csr31 |= fcsr & FPU_CSR_ABS2008;
if ((fcsr0 ^ fcsr1) & FPU_CSR_NAN2008)
c->fpu_msk31 &= ~FPU_CSR_NAN2008;
else
c->fpu_csr31 |= fcsr & FPU_CSR_NAN2008;
} else {
c->options |= MIPS_CPU_NAN_LEGACY;
}
write_c0_status(sr);
} else {
c->options |= MIPS_CPU_NAN_LEGACY;
}
}
/*
* Set the IEEE 754 NaN encodings and ABS.fmt/NEG.fmt execution modes
* for the FPU emulator. Clear the flags where required in case called
* from `fpu_disable', to override details obtained from FPU hardware.
*/
static void cpu_set_nofpu_2008(struct cpuinfo_mips *c)
{
c->fpu_csr31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
if (c->isa_level & (MIPS_CPU_ISA_M32R1 | MIPS_CPU_ISA_M64R1 |
MIPS_CPU_ISA_M32R2 | MIPS_CPU_ISA_M64R2 |
MIPS_CPU_ISA_M32R6 | MIPS_CPU_ISA_M64R6)) {
c->options |= MIPS_CPU_NAN_2008 | MIPS_CPU_NAN_LEGACY;
c->fpu_msk31 &= ~(FPU_CSR_ABS2008 | FPU_CSR_NAN2008);
} else {
c->options &= ~MIPS_CPU_NAN_2008;
c->options |= MIPS_CPU_NAN_LEGACY;
c->fpu_msk31 |= FPU_CSR_ABS2008 | FPU_CSR_NAN2008;
}
}
/* /*
* Set the FIR feature flags for the FPU emulator. * Set the FIR feature flags for the FPU emulator.
*/ */
...@@ -139,7 +211,7 @@ static void cpu_set_fpu_opts(struct cpuinfo_mips *c) ...@@ -139,7 +211,7 @@ static void cpu_set_fpu_opts(struct cpuinfo_mips *c)
} }
cpu_set_fpu_fcsr_mask(c); cpu_set_fpu_fcsr_mask(c);
c->options |= MIPS_CPU_NAN_LEGACY; cpu_set_fpu_2008(c);
} }
/* /*
...@@ -150,7 +222,7 @@ static void cpu_set_nofpu_opts(struct cpuinfo_mips *c) ...@@ -150,7 +222,7 @@ static void cpu_set_nofpu_opts(struct cpuinfo_mips *c)
c->options &= ~MIPS_CPU_FPU; c->options &= ~MIPS_CPU_FPU;
c->fpu_msk31 = mips_nofpu_msk31; c->fpu_msk31 = mips_nofpu_msk31;
c->options |= MIPS_CPU_NAN_LEGACY; cpu_set_nofpu_2008(c);
cpu_set_nofpu_id(c); cpu_set_nofpu_id(c);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment