aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRuslan Bukin <br@FreeBSD.org>2016-10-31 15:33:58 +0000
committerRuslan Bukin <br@FreeBSD.org>2016-10-31 15:33:58 +0000
commit5bca221511e448277905383c6c08180e624c7460 (patch)
tree6e8b7ee360ff41786ad352e2b2797425cfbd6255
parentad9f2cecd74098261d39c1b2a0e85908fa9e122f (diff)
downloadsrc-5bca221511e448277905383c6c08180e624c7460.tar.gz
src-5bca221511e448277905383c6c08180e624c7460.zip
Add full softfloat and hardfloat support for MIPS.
This adds new target architectures for hardfloat: mipselhf mipshf mips64elhf mips64hf. Tested in QEMU only. Sponsored by: DARPA, AFRL Sponsored by: HEIF5 Differential Revision: https://reviews.freebsd.org/D8376
Notes
Notes: svn path=/head/; revision=308130
-rw-r--r--Makefile4
-rw-r--r--Makefile.inc14
-rw-r--r--gnu/lib/libgcc/Makefile2
-rw-r--r--gnu/usr.bin/binutils/Makefile.inc04
-rw-r--r--gnu/usr.bin/binutils/ld/Makefile.mips2
-rw-r--r--gnu/usr.bin/binutils/libbfd/Makefile.mips2
-rw-r--r--gnu/usr.bin/cc/Makefile.inc2
-rw-r--r--gnu/usr.bin/cc/Makefile.tgt4
-rw-r--r--gnu/usr.bin/gdb/Makefile.inc2
-rw-r--r--gnu/usr.bin/gdb/libgdb/Makefile2
-rw-r--r--lib/libc/Makefile2
-rw-r--r--lib/libc/mips/Makefile.inc2
-rw-r--r--lib/libc/mips/Symbol.map4
-rw-r--r--lib/libc/mips/gen/Makefile.inc2
-rw-r--r--lib/libc/mips/gen/flt_rounds.c20
-rw-r--r--lib/msun/mips/Makefile.inc4
-rw-r--r--lib/msun/mips/Symbol.map8
-rw-r--r--lib/msun/mips/fenv.c14
-rw-r--r--lib/msun/mips/fenv.h166
-rw-r--r--share/man/man7/arch.722
-rw-r--r--share/mk/bsd.cpu.mk3
-rw-r--r--share/mk/bsd.endian.mk2
-rw-r--r--share/mk/sys.mk2
-rw-r--r--sys/boot/Makefile.ficl2
-rw-r--r--sys/boot/common/Makefile.inc2
-rw-r--r--sys/boot/mips/uboot/Makefile2
-rw-r--r--sys/conf/kern.mk3
-rw-r--r--sys/mips/include/float.h4
-rw-r--r--sys/mips/mips/exception.S6
-rw-r--r--sys/mips/mips/locore.S2
-rw-r--r--sys/mips/mips/swtch.S16
-rw-r--r--sys/mips/mips/trap.c7
32 files changed, 235 insertions, 88 deletions
diff --git a/Makefile b/Makefile
index b5d51341135e..5904a3f967e3 100644
--- a/Makefile
+++ b/Makefile
@@ -239,7 +239,7 @@ _MAKE+= MK_META_MODE=no
_TARGET_ARCH= ${TARGET:S/pc98/i386/:S/arm64/aarch64/}
.elif !defined(TARGET) && defined(TARGET_ARCH) && \
${TARGET_ARCH} != ${MACHINE_ARCH}
-_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64/riscv/}
+_TARGET= ${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/aarch64/arm64/:C/powerpc64/powerpc/:C/powerpcspe/powerpc/:C/riscv64/riscv/}
.endif
.if defined(TARGET) && !defined(_TARGET)
_TARGET=${TARGET}
@@ -421,7 +421,7 @@ TARGETS?=amd64 arm arm64 i386 mips pc98 powerpc sparc64
_UNIVERSE_TARGETS= ${TARGETS}
TARGET_ARCHES_arm?= arm armeb armv6
TARGET_ARCHES_arm64?= aarch64
-TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32
+TARGET_ARCHES_mips?= mipsel mips mips64el mips64 mipsn32 mipselhf mipshf mips64elhf mips64hf
TARGET_ARCHES_powerpc?= powerpc powerpc64 powerpcspe
TARGET_ARCHES_pc98?= i386
.for target in ${TARGETS}
diff --git a/Makefile.inc1 b/Makefile.inc1
index 476c05431d2a..931af3134669 100644
--- a/Makefile.inc1
+++ b/Makefile.inc1
@@ -356,6 +356,10 @@ KNOWN_ARCHES?= aarch64/arm64 \
mipsn32el/mips \
mips64/mips \
mipsn32/mips \
+ mipshf/mips \
+ mipselhf/mips \
+ mips64elhf/mips \
+ mips64hf/mips \
powerpc \
powerpc64/powerpc \
powerpcspe/powerpc \
diff --git a/gnu/lib/libgcc/Makefile b/gnu/lib/libgcc/Makefile
index 3186458f0866..fba02ed935df 100644
--- a/gnu/lib/libgcc/Makefile
+++ b/gnu/lib/libgcc/Makefile
@@ -165,7 +165,7 @@ LIBADD+= compiler_rt
.if ${TARGET_CPUARCH} == mips
LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c
# ABIs other than o32 need this
-.if ${TARGET_ARCH} != "mips" && ${TARGET_ARCH} != "mipsel"
+.if ${TARGET_ARCH:Mmips64*} != "" || ${TARGET_ARCH:Mmipsn32*} != ""
LIB2FUNCS_EXTRA+= floatdidf.c fixunsdfsi.c
LIB2FUNCS_EXTRA+= floatdisf.c floatundidf.c
LIB2FUNCS_EXTRA+= fixsfdi.c floatundisf.c
diff --git a/gnu/usr.bin/binutils/Makefile.inc0 b/gnu/usr.bin/binutils/Makefile.inc0
index 597d451c8a10..62d03cd0a461 100644
--- a/gnu/usr.bin/binutils/Makefile.inc0
+++ b/gnu/usr.bin/binutils/Makefile.inc0
@@ -7,7 +7,7 @@
VERSION= "2.17.50 [FreeBSD] 2007-07-03"
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
@@ -17,7 +17,7 @@ TARGET_OS?= freebsd
BINUTILS_ARCH=${TARGET_ARCH:C/amd64/x86_64/}
TARGET_TUPLE?= ${BINUTILS_ARCH}-${TARGET_VENDOR}-${TARGET_OS}
.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
- (${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
+ (${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el*} == "")
TARGET_BIG_ENDIAN=t
.endif
diff --git a/gnu/usr.bin/binutils/ld/Makefile.mips b/gnu/usr.bin/binutils/ld/Makefile.mips
index 8a7dfbb5f116..afc651cfca9d 100644
--- a/gnu/usr.bin/binutils/ld/Makefile.mips
+++ b/gnu/usr.bin/binutils/ld/Makefile.mips
@@ -1,6 +1,6 @@
# $FreeBSD$
-.if ${TARGET_ARCH:Mmips*el} != ""
+.if ${TARGET_ARCH:Mmips*el*} != ""
_EMULATION_ENDIAN=l
.else
_EMULATION_ENDIAN=b
diff --git a/gnu/usr.bin/binutils/libbfd/Makefile.mips b/gnu/usr.bin/binutils/libbfd/Makefile.mips
index 02026ba5c087..9a2781a410e2 100644
--- a/gnu/usr.bin/binutils/libbfd/Makefile.mips
+++ b/gnu/usr.bin/binutils/libbfd/Makefile.mips
@@ -1,6 +1,6 @@
# $FreeBSD$
-.if ${TARGET_ARCH:Mmips*el} != ""
+.if ${TARGET_ARCH:Mmips*el*} != ""
_EMULATION_ENDIAN=little
.else
_EMULATION_ENDIAN=big
diff --git a/gnu/usr.bin/cc/Makefile.inc b/gnu/usr.bin/cc/Makefile.inc
index 1d66b3dee7ff..3f053948bada 100644
--- a/gnu/usr.bin/cc/Makefile.inc
+++ b/gnu/usr.bin/cc/Makefile.inc
@@ -39,7 +39,7 @@ CFLAGS += -DFREEBSD_ARCH_armv6
.endif
.if ${TARGET_CPUARCH} == "mips"
-.if ${TARGET_ARCH:Mmips*el} != ""
+.if ${TARGET_ARCH:Mmips*el*} != ""
CFLAGS += -DTARGET_ENDIAN_DEFAULT=0
.endif
diff --git a/gnu/usr.bin/cc/Makefile.tgt b/gnu/usr.bin/cc/Makefile.tgt
index ca2d2ed43e26..3acd4d7c9295 100644
--- a/gnu/usr.bin/cc/Makefile.tgt
+++ b/gnu/usr.bin/cc/Makefile.tgt
@@ -4,7 +4,7 @@
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
@@ -15,7 +15,7 @@ GCC_CPU=${TARGET_CPUARCH:C/amd64/i386/:C/powerpc/rs6000/:C/sparc64/sparc/}
TARGET_CPU_DEFAULT= TARGET_CPU_ultrasparc
.endif
.if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb" || \
- (${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el} == "")
+ (${TARGET_CPUARCH} == "mips" && ${TARGET_ARCH:Mmips*el*} == "")
TARGET_BIG_ENDIAN=t
.endif
.if ${TARGET_ARCH} == "powerpc64"
diff --git a/gnu/usr.bin/gdb/Makefile.inc b/gnu/usr.bin/gdb/Makefile.inc
index 5bce6a91f01e..c9b6603f1992 100644
--- a/gnu/usr.bin/gdb/Makefile.inc
+++ b/gnu/usr.bin/gdb/Makefile.inc
@@ -23,7 +23,7 @@ OBJ_RL= ${OBJ_ROOT}/../lib/libreadline/readline
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
diff --git a/gnu/usr.bin/gdb/libgdb/Makefile b/gnu/usr.bin/gdb/libgdb/Makefile
index 71bb9ff494da..272ede7ded4b 100644
--- a/gnu/usr.bin/gdb/libgdb/Makefile
+++ b/gnu/usr.bin/gdb/libgdb/Makefile
@@ -4,7 +4,7 @@
# MACHINE_CPUARCH, but there's no easy way to export make functions...
.if defined(TARGET_ARCH)
-TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
+TARGET_CPUARCH=${TARGET_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb)?/arm/:C/powerpc(64|spe)/powerpc/}
.else
TARGET_CPUARCH=${MACHINE_CPUARCH}
.endif
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index a97b6fcdedb4..99ddfc2e8f7f 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -111,7 +111,7 @@ NOASM=
.include "${LIBC_SRCTOP}/xdr/Makefile.inc"
.if (${LIBC_ARCH} == "arm" && \
(${MACHINE_ARCH:Marmv6*} == "" || (defined(CPUTYPE) && ${CPUTYPE:M*soft*}))) || \
- ${LIBC_ARCH} == "mips"
+ (${LIBC_ARCH} == "mips" && ${MACHINE_ARCH:Mmips*hf} == "")
.include "${LIBC_SRCTOP}/softfloat/Makefile.inc"
.endif
.if ${LIBC_ARCH} == "i386" || ${LIBC_ARCH} == "amd64"
diff --git a/lib/libc/mips/Makefile.inc b/lib/libc/mips/Makefile.inc
index 4ec20d47d1dd..54ce38e49bfa 100644
--- a/lib/libc/mips/Makefile.inc
+++ b/lib/libc/mips/Makefile.inc
@@ -1,7 +1,9 @@
# $NetBSD: Makefile.inc,v 1.7 2005/09/17 11:49:39 tsutsui Exp $
# $FreeBSD$
+.if ${MACHINE_ARCH:Mmips*hf} == ""
CFLAGS+=-DSOFTFLOAT
+.endif
MDSRCS+= machdep_ldisd.c
SYM_MAPS+= ${LIBC_SRCTOP}/mips/Symbol.map
diff --git a/lib/libc/mips/Symbol.map b/lib/libc/mips/Symbol.map
index 38680807adc4..9791359c93f6 100644
--- a/lib/libc/mips/Symbol.map
+++ b/lib/libc/mips/Symbol.map
@@ -31,6 +31,10 @@ FBSD_1.0 {
sbrk;
};
+FBSD_1.3 {
+ __flt_rounds;
+};
+
FBSDprivate_1.0 {
/* PSEUDO syscalls */
__sys_getlogin;
diff --git a/lib/libc/mips/gen/Makefile.inc b/lib/libc/mips/gen/Makefile.inc
index a186fda62036..56fa380f7777 100644
--- a/lib/libc/mips/gen/Makefile.inc
+++ b/lib/libc/mips/gen/Makefile.inc
@@ -1,7 +1,7 @@
# $NetBSD: Makefile.inc,v 1.27 2005/10/07 17:16:40 tsutsui Exp $
# $FreeBSD$
-SRCS+= infinity.c fabs.c ldexp.c
+SRCS+= infinity.c fabs.c ldexp.c flt_rounds.c
# SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
# fpsetround.c fpsetsticky.c
diff --git a/lib/libc/mips/gen/flt_rounds.c b/lib/libc/mips/gen/flt_rounds.c
index 9fc64a537053..73428d907d11 100644
--- a/lib/libc/mips/gen/flt_rounds.c
+++ b/lib/libc/mips/gen/flt_rounds.c
@@ -11,7 +11,14 @@ __FBSDID("$FreeBSD$");
__RCSID("$NetBSD: flt_rounds.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
#endif /* LIBC_SCCS and not lint */
-#include <machine/float.h>
+#include <fenv.h>
+#include <float.h>
+
+#ifdef SOFTFLOAT
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+#endif
static const int map[] = {
1, /* round to nearest */
@@ -23,8 +30,13 @@ static const int map[] = {
int
__flt_rounds()
{
- int x;
+ int mode;
+
+#ifdef SOFTFLOAT
+ mode = __softfloat_float_rounding_mode;
+#else
+ __asm __volatile("cfc1 %0,$31" : "=r" (mode));
+#endif
- __asm("cfc1 %0,$31" : "=r" (x));
- return map[x & 0x03];
+ return map[mode & 0x03];
}
diff --git a/lib/msun/mips/Makefile.inc b/lib/msun/mips/Makefile.inc
index 8c1a4864f4cf..b05f4fa3812b 100644
--- a/lib/msun/mips/Makefile.inc
+++ b/lib/msun/mips/Makefile.inc
@@ -1,4 +1,8 @@
# $FreeBSD$
+.if ${MACHINE_ARCH:Mmips*hf} == ""
+CFLAGS+=-DSOFTFLOAT
+.endif
+
LDBL_PREC = 53
SYM_MAPS += ${.CURDIR}/mips/Symbol.map
diff --git a/lib/msun/mips/Symbol.map b/lib/msun/mips/Symbol.map
index 971112e30c8a..081294cf5562 100644
--- a/lib/msun/mips/Symbol.map
+++ b/lib/msun/mips/Symbol.map
@@ -5,9 +5,17 @@ FBSD_1.0 {
};
FBSD_1.3 {
+ feclearexcept;
+ fegetexceptflag;
fesetexceptflag;
feraiseexcept;
+ fetestexcept;
+ fegetround;
+ fesetround;
fegetenv;
feholdexcept;
feupdateenv;
+ feenableexcept;
+ fedisableexcept;
+ fegetexcept;
};
diff --git a/lib/msun/mips/fenv.c b/lib/msun/mips/fenv.c
index a5a5c03d3a74..64beb704c74e 100644
--- a/lib/msun/mips/fenv.c
+++ b/lib/msun/mips/fenv.c
@@ -39,6 +39,17 @@
*/
const fenv_t __fe_dfl_env = 0;
+#ifdef SOFTFLOAT
+#define __set_env(env, flags, mask, rnd) env = ((flags) \
+ | (mask)<<_FPUSW_SHIFT \
+ | (rnd) << 24)
+#define __env_flags(env) ((env) & FE_ALL_EXCEPT)
+#define __env_mask(env) (((env) >> _FPUSW_SHIFT) \
+ & FE_ALL_EXCEPT)
+#define __env_round(env) (((env) >> 24) & _ROUND_MASK)
+#include "fenv-softfloat.h"
+#endif
+
extern inline int feclearexcept(int __excepts);
extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
@@ -50,3 +61,6 @@ extern inline int fegetenv(fenv_t *__envp);
extern inline int feholdexcept(fenv_t *__envp);
extern inline int fesetenv(const fenv_t *__envp);
extern inline int feupdateenv(const fenv_t *__envp);
+extern inline int feenableexcept(int __mask);
+extern inline int fedisableexcept(int __mask);
+extern inline int fegetexcept(void);
diff --git a/lib/msun/mips/fenv.h b/lib/msun/mips/fenv.h
index f11499806bea..498af3471b5d 100644
--- a/lib/msun/mips/fenv.h
+++ b/lib/msun/mips/fenv.h
@@ -39,11 +39,21 @@ typedef __uint32_t fenv_t;
typedef __uint32_t fexcept_t;
/* Exception flags */
+#ifdef SOFTFLOAT
+#define _FPUSW_SHIFT 16
#define FE_INVALID 0x0001
#define FE_DIVBYZERO 0x0002
#define FE_OVERFLOW 0x0004
#define FE_UNDERFLOW 0x0008
#define FE_INEXACT 0x0010
+#else
+#define _FCSR_CAUSE_SHIFT 10
+#define FE_INVALID 0x0040
+#define FE_DIVBYZERO 0x0020
+#define FE_OVERFLOW 0x0010
+#define FE_UNDERFLOW 0x0008
+#define FE_INEXACT 0x0004
+#endif
#define FE_ALL_EXCEPT (FE_DIVBYZERO | FE_INEXACT | \
FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
@@ -61,104 +71,135 @@ extern const fenv_t __fe_dfl_env;
#define FE_DFL_ENV (&__fe_dfl_env)
/* We need to be able to map status flag positions to mask flag positions */
-#define _FPUSW_SHIFT 16
-#define _ENABLE_MASK (FE_ALL_EXCEPT << _FPUSW_SHIFT)
+#define _ENABLE_SHIFT 5
+#define _ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
-#ifdef ARM_HARD_FLOAT
-#define __rfs(__fpsr) __asm __volatile("rfs %0" : "=r" (*(__fpsr)))
-#define __wfs(__fpsr) __asm __volatile("wfs %0" : : "r" (__fpsr))
-#else
-#define __rfs(__fpsr)
-#define __wfs(__fpsr)
+#ifndef SOFTFLOAT
+#define __cfc1(__fcsr) __asm __volatile("cfc1 %0, $31" : "=r" (__fcsr))
+#define __ctc1(__fcsr) __asm __volatile("ctc1 %0, $31" :: "r" (__fcsr))
#endif
+#ifdef SOFTFLOAT
+int feclearexcept(int __excepts);
+int fegetexceptflag(fexcept_t *__flagp, int __excepts);
+int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
+int feraiseexcept(int __excepts);
+int fetestexcept(int __excepts);
+int fegetround(void);
+int fesetround(int __round);
+int fegetenv(fenv_t *__envp);
+int feholdexcept(fenv_t *__envp);
+int fesetenv(const fenv_t *__envp);
+int feupdateenv(const fenv_t *__envp);
+#else
__fenv_static inline int
feclearexcept(int __excepts)
{
- fexcept_t __fpsr;
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
+ __ctc1(fcsr);
- __rfs(&__fpsr);
- __fpsr &= ~__excepts;
- __wfs(__fpsr);
return (0);
}
__fenv_static inline int
fegetexceptflag(fexcept_t *__flagp, int __excepts)
{
- fexcept_t __fpsr;
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ *__flagp = fcsr & __excepts;
- __rfs(&__fpsr);
- *__flagp = __fpsr & __excepts;
return (0);
}
__fenv_static inline int
fesetexceptflag(const fexcept_t *__flagp, int __excepts)
{
- fexcept_t __fpsr;
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr &= ~__excepts;
+ fcsr |= *__flagp & __excepts;
+ __ctc1(fcsr);
- __rfs(&__fpsr);
- __fpsr &= ~__excepts;
- __fpsr |= *__flagp & __excepts;
- __wfs(__fpsr);
return (0);
}
__fenv_static inline int
feraiseexcept(int __excepts)
{
- fexcept_t __ex = __excepts;
+ fexcept_t fcsr;
+
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+ fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
+ __ctc1(fcsr);
- fesetexceptflag(&__ex, __excepts); /* XXX */
return (0);
}
__fenv_static inline int
fetestexcept(int __excepts)
{
- fexcept_t __fpsr;
+ fexcept_t fcsr;
- __rfs(&__fpsr);
- return (__fpsr & __excepts);
+ __excepts &= FE_ALL_EXCEPT;
+ __cfc1(fcsr);
+
+ return (fcsr & __excepts);
}
__fenv_static inline int
fegetround(void)
{
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
- /*
- * Apparently, the rounding mode is specified as part of the
- * instruction format on ARM, so the dynamic rounding mode is
- * indeterminate. Some FPUs may differ.
- */
- return (-1);
+ return (fcsr & _ROUND_MASK);
}
__fenv_static inline int
fesetround(int __round)
{
+ fexcept_t fcsr;
+
+ if (__round & ~_ROUND_MASK)
+ return (-1);
- return (-1);
+ __cfc1(fcsr);
+ fcsr &= ~_ROUND_MASK;
+ fcsr |= __round;
+ __ctc1(fcsr);
+
+ return (0);
}
__fenv_static inline int
fegetenv(fenv_t *__envp)
{
- __rfs(__envp);
+ __cfc1(*__envp);
+
return (0);
}
__fenv_static inline int
feholdexcept(fenv_t *__envp)
{
- fenv_t __env;
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+ *__envp = fcsr;
+ fcsr &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
+ __ctc1(fcsr);
- __rfs(&__env);
- *__envp = __env;
- __env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
- __wfs(__env);
return (0);
}
@@ -166,56 +207,69 @@ __fenv_static inline int
fesetenv(const fenv_t *__envp)
{
- __wfs(*__envp);
+ __ctc1(*__envp);
+
return (0);
}
__fenv_static inline int
feupdateenv(const fenv_t *__envp)
{
- fexcept_t __fpsr;
+ fexcept_t fcsr;
+
+ __cfc1(fcsr);
+ fesetenv(__envp);
+ feraiseexcept(fcsr);
- __rfs(&__fpsr);
- __wfs(*__envp);
- feraiseexcept(__fpsr & FE_ALL_EXCEPT);
return (0);
}
+#endif /* !SOFTFLOAT */
#if __BSD_VISIBLE
/* We currently provide no external definitions of the functions below. */
+#ifdef SOFTFLOAT
+int feenableexcept(int __mask);
+int fedisableexcept(int __mask);
+int fegetexcept(void);
+#else
static inline int
feenableexcept(int __mask)
{
- fenv_t __old_fpsr, __new_fpsr;
+ fenv_t __old_fcsr, __new_fcsr;
+
+ __cfc1(__old_fcsr);
+ __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
+ __ctc1(__new_fcsr);
- __rfs(&__old_fpsr);
- __new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
- __wfs(__new_fpsr);
- return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
}
static inline int
fedisableexcept(int __mask)
{
- fenv_t __old_fpsr, __new_fpsr;
+ fenv_t __old_fcsr, __new_fcsr;
+
+ __cfc1(__old_fcsr);
+ __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
+ __ctc1(__new_fcsr);
- __rfs(&__old_fpsr);
- __new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
- __wfs(__new_fpsr);
- return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+ return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
}
static inline int
fegetexcept(void)
{
- fenv_t __fpsr;
+ fexcept_t fcsr;
- __rfs(&__fpsr);
- return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+ __cfc1(fcsr);
+
+ return ((fcsr & _ENABLE_MASK) >> _ENABLE_SHIFT);
}
+#endif /* !SOFTFLOAT */
+
#endif /* __BSD_VISIBLE */
__END_DECLS
diff --git a/share/man/man7/arch.7 b/share/man/man7/arch.7
index 488cd05b1f90..d198c98665bf 100644
--- a/share/man/man7/arch.7
+++ b/share/man/man7/arch.7
@@ -57,9 +57,13 @@ On all supported architectures,
.It i386 Ta 4 Ta 12
.It mips Ta 4 Ta 8
.It mipsel Ta 4 Ta 8
+.It mipselhf Ta 4 Ta 8
+.It mipshf Ta 4 Ta 8
.It mipsn32 Ta 4 Ta 8
.It mips64 Ta 8 Ta 8
.It mips64el Ta 8 Ta 8
+.It mips64elhf Ta 8 Ta 8
+.It mips64hf Ta 8 Ta 8
.It powerpc Ta 4 Ta 8
.It powerpc64 Ta 8 Ta 8
.It riscv Ta 8 Ta
@@ -76,9 +80,13 @@ On all supported architectures,
.It i386 Ta little Ta signed
.It mips Ta big Ta signed
.It mipsel Ta little Ta signed
+.It mipselhf Ta little Ta signed
+.It mipshf Ta big Ta signed
.It mipsn32 Ta big Ta signed
.It mips64 Ta big Ta signed
.It mips64el Ta little Ta signed
+.It mips64elhf Ta little Ta signed
+.It mips64hf Ta big Ta signed
.It powerpc Ta big Ta unsigned
.It powerpc64 Ta big Ta unsigned
.It riscv Ta little Ta signed
@@ -95,9 +103,13 @@ On all supported architectures,
.It i386 Ta 4K, 2M (PAE), 4M
.It mips Ta 4K
.It mipsel Ta 4K
+.It mipselhf Ta 4K
+.It mipshf Ta 4K
.It mipsn32 Ta 4K
.It mips64 Ta 4K
.It mips64el Ta 4K
+.It mips64elhf Ta 4K
+.It mips64hf Ta 4K
.It powerpc Ta 4K
.It powerpc64 Ta 4K
.It riscv Ta 4K
@@ -114,9 +126,13 @@ On all supported architectures,
.It i386 Ta hard Ta hard, 80 bit
.It mips Ta soft Ta identical to double
.It mipsel Ta soft Ta identical to double
-.It mipsn32 Ta soft Ta identical to double
+.It mipselhf Ta hard Ta identical to double
+.It mipshf Ta hard Ta identical to double
+.It mipsn32 Ta soft Ta identical to double
.It mips64 Ta soft Ta identical to double
.It mips64el Ta soft Ta identical to double
+.It mips64elhf Ta hard Ta identical to double
+.It mips64hf Ta hard Ta identical to double
.It powerpc Ta hard Ta hard, double precision
.It powerpc64 Ta hard Ta hard, double precision
.It riscv Ta
@@ -155,9 +171,13 @@ Architecture-specific macros:
.It i386 Ta Dv __i386__
.It mips Ta Dv __mips__, Dv __MIPSEB__, Dv __mips_o32
.It mipsel Ta Dv __mips__, Dv __mips_o32
+.It mipselhf Ta Dv __mips__, Dv __mips_o32
+.It mipshf Ta Dv __mips__, Dv __MIPSEB__, Dv __mips_o32
.It mipsn32 Ta Dv __mips__, Dv __MIPSEB__, Dv __mips_n32
.It mips64 Ta Dv __mips__, Dv __MIPSEB__, Dv __mips_n64
.It mips64el Ta Dv __mips__, Dv __mips_n64
+.It mips64elhf Ta Dv __mips__, Dv __mips_n64
+.It mips64hf Ta Dv __mips__, Dv __MIPSEB__, Dv __mips_n64
.It powerpc Ta Dv __powerpc__
.It powerpc64 Ta Dv __powerpc__, Dv __powerpc64__
.It riscv Ta Dv __riscv__, Dv __riscv64
diff --git a/share/mk/bsd.cpu.mk b/share/mk/bsd.cpu.mk
index 211b6fc87723..5ccfe548cbc1 100644
--- a/share/mk/bsd.cpu.mk
+++ b/share/mk/bsd.cpu.mk
@@ -303,6 +303,9 @@ MACHINE_CPU = v9 ultrasparc ultrasparc3
.if ${MACHINE_CPUARCH} == "mips"
CFLAGS += -G0
+.if ${TARGET_ARCH:Mmips*hf}
+CFLAGS += -mhard-float
+.endif
.endif
########## arm
diff --git a/share/mk/bsd.endian.mk b/share/mk/bsd.endian.mk
index a264b67e0407..eac92c6838f7 100644
--- a/share/mk/bsd.endian.mk
+++ b/share/mk/bsd.endian.mk
@@ -5,7 +5,7 @@
${MACHINE_ARCH} == "i386" || \
(${MACHINE} == "arm" && ${MACHINE_ARCH:Marm*eb*} == "") || \
${MACHINE_CPUARCH} == "riscv" || \
- ${MACHINE_ARCH:Mmips*el} != ""
+ ${MACHINE_ARCH:Mmips*el*} != ""
TARGET_ENDIANNESS= 1234
.elif ${MACHINE_ARCH} == "powerpc" || \
${MACHINE_ARCH} == "powerpc64" || \
diff --git a/share/mk/sys.mk b/share/mk/sys.mk
index 6efa99410d0a..cc4a1feb61bb 100644
--- a/share/mk/sys.mk
+++ b/share/mk/sys.mk
@@ -13,7 +13,7 @@ unix ?= We run FreeBSD, not UNIX.
# and/or endian. This is called MACHINE_CPU in NetBSD, but that's used
# for something different in FreeBSD.
#
-MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64/riscv/}
+MACHINE_CPUARCH=${MACHINE_ARCH:C/mips(n32|64)?(el)?(hf)?/mips/:C/arm(v6)?(eb|hf)?/arm/:C/powerpc(64|spe)/powerpc/:C/riscv64/riscv/}
.endif
diff --git a/sys/boot/Makefile.ficl b/sys/boot/Makefile.ficl
index de1427aa4285..ef9a11de347a 100644
--- a/sys/boot/Makefile.ficl
+++ b/sys/boot/Makefile.ficl
@@ -6,7 +6,7 @@ FICLDIR?= ${SRCTOP}/sys/boot/ficl
.if ${MACHINE_CPUARCH} == "amd64" && defined(FICL32)
FICL_CPUARCH= i386
-.elif ${MACHINE_ARCH} == "mips64" || ${MACHINE_ARCH} == "mips64el"
+.elif ${MACHINE_ARCH:Mmips64*} != ""
FICL_CPUARCH= mips64
.else
FICL_CPUARCH= ${MACHINE_CPUARCH}
diff --git a/sys/boot/common/Makefile.inc b/sys/boot/common/Makefile.inc
index 6086a3b22fa0..a7e8ea75561b 100644
--- a/sys/boot/common/Makefile.inc
+++ b/sys/boot/common/Makefile.inc
@@ -18,7 +18,7 @@ SRCS+= load_elf32.c reloc_elf32.c
SRCS+= load_elf64.c reloc_elf64.c
.elif ${MACHINE_CPUARCH} == "sparc64"
SRCS+= load_elf64.c reloc_elf64.c
-.elif ${MACHINE_ARCH} == "mips64" || ${MACHINE_ARCH} == "mips64el"
+.elif ${MACHINE_ARCH:Mmips64*} != ""
SRCS+= load_elf64.c reloc_elf64.c
.elif ${MACHINE} == "mips"
SRCS+= load_elf32.c reloc_elf32.c
diff --git a/sys/boot/mips/uboot/Makefile b/sys/boot/mips/uboot/Makefile
index 6be362c86564..05761b099b6b 100644
--- a/sys/boot/mips/uboot/Makefile
+++ b/sys/boot/mips/uboot/Makefile
@@ -85,7 +85,7 @@ LIBFDT= ${.OBJDIR}/../../fdt/libfdt.a
# Enable BootForth
BOOT_FORTH= yes
CFLAGS+= -DBOOT_FORTH -I${.CURDIR}/../../ficl
-.if ${MACHINE_ARCH} == "mips64" || ${MACHINE_ARCH} == "mips64el"
+.if ${MACHINE_ARCH:Mmips64*} != ""
CFLAGS+= -I${.CURDIR}/../../ficl/mips64
.else
CFLAGS+= -I${.CURDIR}/../../ficl/mips
diff --git a/sys/conf/kern.mk b/sys/conf/kern.mk
index 15a6bf557013..fb8ade289c8b 100644
--- a/sys/conf/kern.mk
+++ b/sys/conf/kern.mk
@@ -184,6 +184,9 @@ CFLAGS.gcc+= -mcall-aixdesc
.if ${MACHINE_CPUARCH} == "mips"
CFLAGS+= -msoft-float
INLINE_LIMIT?= 8000
+.if ${TARGET_ARCH:Mmips*hf} != ""
+CFLAGS+= -DCPU_HAVEFPU
+.endif
.endif
#
diff --git a/sys/mips/include/float.h b/sys/mips/include/float.h
index 86efd02b975c..93a9d5c2fd50 100644
--- a/sys/mips/include/float.h
+++ b/sys/mips/include/float.h
@@ -42,11 +42,7 @@ extern int __flt_rounds(void);
__END_DECLS
#define FLT_RADIX 2 /* b */
-#ifdef CPU_HAVEFPU
#define FLT_ROUNDS __flt_rounds() /* FP addition rounds to nearest */
-#else
-#define FLT_ROUNDS (-1)
-#endif
#if __ISO_C_VISIBLE >= 1999
#define FLT_EVAL_METHOD 0
diff --git a/sys/mips/mips/exception.S b/sys/mips/mips/exception.S
index 725ae65eaaa2..04614737ab99 100644
--- a/sys/mips/mips/exception.S
+++ b/sys/mips/mips/exception.S
@@ -1098,11 +1098,17 @@ END(MipsTLBMissException)
NESTED(MipsFPTrap, CALLFRAME_SIZ, ra)
PTR_SUBU sp, sp, CALLFRAME_SIZ
mfc0 t0, MIPS_COP_0_STATUS
+ HAZARD_DELAY
REG_S ra, CALLFRAME_RA(sp)
.mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
+#if defined(__mips_n64)
+ or t1, t0, MIPS_SR_COP_1_BIT | MIPS_SR_FR
+#else
or t1, t0, MIPS_SR_COP_1_BIT
+#endif
mtc0 t1, MIPS_COP_0_STATUS
+ HAZARD_DELAY
ITLBNOPFIX
cfc1 t1, MIPS_FPU_CSR # stall til FP done
cfc1 t1, MIPS_FPU_CSR # now get status
diff --git a/sys/mips/mips/locore.S b/sys/mips/mips/locore.S
index 4e2173c583d3..37421d8f5003 100644
--- a/sys/mips/mips/locore.S
+++ b/sys/mips/mips/locore.S
@@ -118,7 +118,7 @@ VECTOR(_locore, unknown)
*/
li t1, MIPS_SR_COP_1_BIT
#ifdef __mips_n64
- or t1, MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX
+ or t1, MIPS_SR_KX | MIPS_SR_SX | MIPS_SR_UX | MIPS_SR_FR
#endif
#endif
/*
diff --git a/sys/mips/mips/swtch.S b/sys/mips/mips/swtch.S
index aff18acb36cc..ae33c39edd46 100644
--- a/sys/mips/mips/swtch.S
+++ b/sys/mips/mips/swtch.S
@@ -415,8 +415,14 @@ LEAF(MipsSwitchFPState)
.set push
.set hardfloat
mfc0 t1, MIPS_COP_0_STATUS # Save old SR
- li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
+ HAZARD_DELAY
+#if defined(__mips_n64)
+ or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor
+#else
+ or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor
+#endif
mtc0 t0, MIPS_COP_0_STATUS
+ HAZARD_DELAY
ITLBNOPFIX
beq a0, zero, 1f # skip save if NULL pointer
@@ -540,8 +546,14 @@ LEAF(MipsSaveCurFPState)
.set hardfloat
PTR_L a0, TD_PCB(a0) # get pointer to pcb for thread
mfc0 t1, MIPS_COP_0_STATUS # Disable interrupts and
- li t0, MIPS_SR_COP_1_BIT # enable the coprocessor
+ HAZARD_DELAY
+#if defined(__mips_n64)
+ or t0, t1, MIPS_SR_COP_1_BIT | MIPS_SR_FR # enable the coprocessor
+#else
+ or t0, t1, MIPS_SR_COP_1_BIT # enable the coprocessor
+#endif
mtc0 t0, MIPS_COP_0_STATUS
+ HAZARD_DELAY
ITLBNOPFIX
GET_CPU_PCPU(a1)
PTR_S zero, PC_FPCURTHREAD(a1) # indicate state has been saved
diff --git a/sys/mips/mips/trap.c b/sys/mips/mips/trap.c
index e14b12be2139..05789ae7e4da 100644
--- a/sys/mips/mips/trap.c
+++ b/sys/mips/mips/trap.c
@@ -590,7 +590,8 @@ trap(struct trapframe *trapframe)
break;
}
if ((last_badvaddr == this_badvaddr) &&
- ((type & ~T_USER) != T_SYSCALL)) {
+ ((type & ~T_USER) != T_SYSCALL) &&
+ ((type & ~T_USER) != T_COP_UNUSABLE)) {
if (++count == 3) {
trap_frame_dump(trapframe);
panic("too many faults at %p\n", (void *)last_badvaddr);
@@ -980,7 +981,11 @@ dofault:
addr = trapframe->pc;
MipsSwitchFPState(PCPU_GET(fpcurthread), td->td_frame);
PCPU_SET(fpcurthread, td);
+#if defined(__mips_n64)
+ td->td_frame->sr |= MIPS_SR_COP_1_BIT | MIPS_SR_FR;
+#else
td->td_frame->sr |= MIPS_SR_COP_1_BIT;
+#endif
td->td_md.md_flags |= MDTD_FPUSED;
goto out;
#endif