Index: Makefile
===================================================================
--- Makefile
+++ Makefile
@@ -239,7 +239,7 @@
 _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 @@
 _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}
Index: Makefile.inc1
===================================================================
--- Makefile.inc1
+++ Makefile.inc1
@@ -356,6 +356,10 @@
 		mipsn32el/mips \
 		mips64/mips \
 		mipsn32/mips \
+		mipshf/mips \
+		mipselhf/mips \
+		mips64elhf/mips \
+		mips64hf/mips \
 		powerpc \
 		powerpc64/powerpc \
 		powerpcspe/powerpc \
Index: gnu/lib/libgcc/Makefile
===================================================================
--- gnu/lib/libgcc/Makefile
+++ gnu/lib/libgcc/Makefile
@@ -165,7 +165,7 @@
 .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
Index: gnu/usr.bin/binutils/Makefile.inc0
===================================================================
--- gnu/usr.bin/binutils/Makefile.inc0
+++ 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 @@
 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
 
Index: gnu/usr.bin/binutils/ld/Makefile.mips
===================================================================
--- gnu/usr.bin/binutils/ld/Makefile.mips
+++ 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
Index: gnu/usr.bin/binutils/libbfd/Makefile.mips
===================================================================
--- gnu/usr.bin/binutils/libbfd/Makefile.mips
+++ 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
Index: gnu/usr.bin/cc/Makefile.inc
===================================================================
--- gnu/usr.bin/cc/Makefile.inc
+++ gnu/usr.bin/cc/Makefile.inc
@@ -39,7 +39,7 @@
 .endif
 
 .if ${TARGET_CPUARCH} == "mips"
-.if ${TARGET_ARCH:Mmips*el} != ""
+.if ${TARGET_ARCH:Mmips*el*} != ""
 CFLAGS += -DTARGET_ENDIAN_DEFAULT=0
 .endif
 
Index: gnu/usr.bin/cc/Makefile.tgt
===================================================================
--- gnu/usr.bin/cc/Makefile.tgt
+++ 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 @@
 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"
Index: gnu/usr.bin/gdb/Makefile.inc
===================================================================
--- gnu/usr.bin/gdb/Makefile.inc
+++ gnu/usr.bin/gdb/Makefile.inc
@@ -23,7 +23,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
Index: gnu/usr.bin/gdb/libgdb/Makefile
===================================================================
--- gnu/usr.bin/gdb/libgdb/Makefile
+++ 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
Index: lib/libc/Makefile
===================================================================
--- lib/libc/Makefile
+++ lib/libc/Makefile
@@ -111,7 +111,7 @@
 .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"
Index: lib/libc/mips/Makefile.inc
===================================================================
--- lib/libc/mips/Makefile.inc
+++ 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
Index: lib/libc/mips/Symbol.map
===================================================================
--- lib/libc/mips/Symbol.map
+++ lib/libc/mips/Symbol.map
@@ -31,6 +31,10 @@
 	sbrk;
 };
 
+FBSD_1.3 {
+	__flt_rounds;
+};
+
 FBSDprivate_1.0 {
 	/* PSEUDO syscalls */
 	__sys_getlogin;
Index: lib/libc/mips/gen/Makefile.inc
===================================================================
--- lib/libc/mips/gen/Makefile.inc
+++ 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
Index: lib/libc/mips/gen/flt_rounds.c
===================================================================
--- lib/libc/mips/gen/flt_rounds.c
+++ lib/libc/mips/gen/flt_rounds.c
@@ -11,7 +11,14 @@
 __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 @@
 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];
 }
Index: lib/msun/mips/Makefile.inc
===================================================================
--- lib/msun/mips/Makefile.inc
+++ 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
Index: lib/msun/mips/Symbol.map
===================================================================
--- lib/msun/mips/Symbol.map
+++ lib/msun/mips/Symbol.map
@@ -5,9 +5,17 @@
 };
 
 FBSD_1.3 {
+	feclearexcept;
+	fegetexceptflag;
 	fesetexceptflag;
 	feraiseexcept;
+	fetestexcept;
+	fegetround;
+	fesetround;
 	fegetenv;
 	feholdexcept;
 	feupdateenv;
+	feenableexcept;
+	fedisableexcept;
+	fegetexcept;
 };
Index: lib/msun/mips/fenv.h
===================================================================
--- lib/msun/mips/fenv.h
+++ lib/msun/mips/fenv.h
@@ -39,11 +39,21 @@
 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 @@
 #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 @@
 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
Index: lib/msun/mips/fenv.c
===================================================================
--- lib/msun/mips/fenv.c
+++ 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 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);
Index: share/man/man7/arch.7
===================================================================
--- share/man/man7/arch.7
+++ share/man/man7/arch.7
@@ -57,9 +57,13 @@
 .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 @@
 .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 @@
 .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 @@
 .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 @@
 .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
Index: share/mk/bsd.cpu.mk
===================================================================
--- share/mk/bsd.cpu.mk
+++ share/mk/bsd.cpu.mk
@@ -303,6 +303,9 @@
 
 .if ${MACHINE_CPUARCH} == "mips"
 CFLAGS += -G0
+.if ${TARGET_ARCH:Mmips*hf}
+CFLAGS += -mhard-float
+.endif
 .endif
 
 ########## arm
Index: share/mk/bsd.endian.mk
===================================================================
--- share/mk/bsd.endian.mk
+++ 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" || \
Index: share/mk/sys.mk
===================================================================
--- share/mk/sys.mk
+++ share/mk/sys.mk
@@ -13,7 +13,7 @@
 # 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
 
 
Index: sys/boot/Makefile.ficl
===================================================================
--- sys/boot/Makefile.ficl
+++ sys/boot/Makefile.ficl
@@ -6,7 +6,7 @@
 
 .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}
Index: sys/boot/common/Makefile.inc
===================================================================
--- sys/boot/common/Makefile.inc
+++ sys/boot/common/Makefile.inc
@@ -18,7 +18,7 @@
 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
Index: sys/boot/mips/uboot/Makefile
===================================================================
--- sys/boot/mips/uboot/Makefile
+++ sys/boot/mips/uboot/Makefile
@@ -85,7 +85,7 @@
 # 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
Index: sys/conf/kern.mk
===================================================================
--- sys/conf/kern.mk
+++ sys/conf/kern.mk
@@ -184,6 +184,9 @@
 .if ${MACHINE_CPUARCH} == "mips"
 CFLAGS+=	-msoft-float
 INLINE_LIMIT?=	8000
+.if ${TARGET_ARCH:Mmips*hf} != ""
+CFLAGS+= -DCPU_HAVEFPU
+.endif
 .endif
 
 #
Index: sys/mips/include/float.h
===================================================================
--- sys/mips/include/float.h
+++ sys/mips/include/float.h
@@ -42,11 +42,7 @@
 __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
Index: sys/mips/mips/exception.S
===================================================================
--- sys/mips/mips/exception.S
+++ sys/mips/mips/exception.S
@@ -1098,11 +1098,17 @@
 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
Index: sys/mips/mips/locore.S
===================================================================
--- sys/mips/mips/locore.S
+++ sys/mips/mips/locore.S
@@ -118,7 +118,7 @@
 	 */
 	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
 	/*
Index: sys/mips/mips/swtch.S
===================================================================
--- sys/mips/mips/swtch.S
+++ sys/mips/mips/swtch.S
@@ -415,8 +415,14 @@
 	.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 @@
 	.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
Index: sys/mips/mips/trap.c
===================================================================
--- sys/mips/mips/trap.c
+++ sys/mips/mips/trap.c
@@ -590,7 +590,8 @@
 			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 @@
 			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
@@ -1028,7 +1033,7 @@
 
 	case T_FPE + T_USER:
 		if (!emulate_fp) {
-			i = SIGILL;
+			i = SIGFPE;
 			addr = trapframe->pc;
 			break;
 		}