diff --git a/config.h.in b/config.h.in
index 40797e7..05da98a 100644
--- a/config.h.in
+++ b/config.h.in
@@ -241,8 +241,12 @@
 /* The pt_chown binary is being built and used by grantpt.  */
 #undef HAVE_PT_CHOWN
 
-/* ports/sysdeps/mips/configure.in  */
+/* sysdeps/mips/configure.in  */
 /* Define if using the IEEE 754-2008 NaN encoding on the MIPS target.  */
 #undef HAVE_MIPS_NAN2008
 
+/* sysdeps/unix/sysv/linux/mips/configure.in  */
+/* Define if the assembler supports the .module fp=xx directive.  */
+#undef HAVE_MIPS_MODULE_FPXX_DIRECTIVE
+
 #endif
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 6501ff2..43aacdc 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1866,6 +1866,13 @@ open_verify (const char *name, struct filebuf *fbp, struct link_map *loader,
 	    }
 	}
 
+#ifdef ELF_MACHINE_NEEDS_PHDR_CHECK
+      if (!__builtin_expect (
+	     elf_machine_phdr_check (phdr, ehdr->e_phnum, fbp->buf, fbp->len,
+				     fd, loader), 1))
+	goto close_and_out;
+#endif
+
       /* Check .note.ABI-tag if present.  */
       for (ph = phdr; ph < &phdr[ehdr->e_phnum]; ++ph)
 	if (ph->p_type == PT_NOTE && ph->p_filesz >= 32 && ph->p_align >= 4)
diff --git a/elf/elf.h b/elf/elf.h
index 40e87b2..dccdee9 100644
--- a/elf/elf.h
+++ b/elf/elf.h
@@ -1631,9 +1631,10 @@ typedef struct
 
 /* Legal values for p_type field of Elf32_Phdr.  */
 
-#define PT_MIPS_REGINFO	0x70000000	/* Register usage information */
-#define PT_MIPS_RTPROC  0x70000001	/* Runtime procedure table. */
-#define PT_MIPS_OPTIONS 0x70000002
+#define PT_MIPS_REGINFO	  0x70000000	/* Register usage information. */
+#define PT_MIPS_RTPROC	  0x70000001	/* Runtime procedure table. */
+#define PT_MIPS_OPTIONS	  0x70000002
+#define PT_MIPS_ABIFLAGS  0x70000003	/* FP mode requirement. */
 
 /* Special program header types.  */
 
@@ -1755,6 +1756,96 @@ typedef struct
 
 typedef Elf32_Addr Elf32_Conflict;
 
+typedef struct
+{
+  /* Version of flags structure.  */
+  Elf32_Half version;
+  /* The level of the ISA: 1-5, 32, 64.  */
+  unsigned char isa_level;
+  /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise.  */
+  unsigned char isa_rev;
+  /* The size of general purpose registers.  */
+  unsigned char gpr_size;
+  /* The size of co-processor 1 registers.  */
+  unsigned char cpr1_size;
+  /* The size of co-processor 2 registers.  */
+  unsigned char cpr2_size;
+  /* The floating-point ABI.  */
+  unsigned char fp_abi;
+  /* Mask of processor-specific extensions.  */
+  Elf32_Word isa_ext;
+  /* Mask of ASEs used.  */
+  Elf32_Word ases;
+  /* Mask of general flags.  */
+  Elf32_Word flags1;
+  Elf32_Word flags2;
+} Elf_ABIFlags_v0;
+
+/* Values for the register size bytes of an abi flags structure.  */
+
+#define AFL_REG_NONE	      0x00	 /* No registers.  */
+#define AFL_REG_32	      0x01	 /* 32-bit registers.  */
+#define AFL_REG_64	      0x02	 /* 64-bit registers.  */
+#define AFL_REG_128	      0x03	 /* 128-bit registers.  */
+
+/* Masks for the ases word of an ABI flags structure.  */
+
+#define AFL_ASE_DSP	      0x00000001 /* DSP ASE.  */
+#define AFL_ASE_DSP64	      0x00000002 /* DSP ASE (64-bit).  */
+#define AFL_ASE_DSPR2	      0x00000004 /* DSP R2 ASE.  */
+#define AFL_ASE_EVA	      0x00000008 /* Enhanced VA Scheme.  */
+#define AFL_ASE_MCU	      0x00000010 /* MCU (MicroController) ASE.  */
+#define AFL_ASE_MDMX	      0x00000020 /* MDMX ASE.  */
+#define AFL_ASE_MIPS3D	      0x00000040 /* MIPS-3D ASE.  */
+#define AFL_ASE_MT	      0x00000080 /* MT ASE.  */
+#define AFL_ASE_SMARTMIPS     0x00000100 /* SmartMIPS ASE.  */
+#define AFL_ASE_VIRT	      0x00000200 /* VZ ASE.  */
+#define AFL_ASE_VIRT64	      0x00000400 /* VZ ASE (64-bit).  */
+#define AFL_ASE_MSA	      0x00000800 /* MSA ASE.  */
+#define AFL_ASE_MSA64	      0x00001000 /* MSA ASE (64-bit).  */
+#define AFL_ASE_MIPS16	      0x00002000 /* MIPS16 ASE.  */
+#define AFL_ASE_MICROMIPS     0x00004000 /* MICROMIPS ASE.  */
+#define AFL_ASE_XPA	      0x00002000 /* XPA ASE.  */
+
+/* Masks for the isa_ext word of an ABI flags structure.  */
+
+#define AFL_EXT_XLR	      0x00000020 /* RMI Xlr instruction.  */
+#define AFL_EXT_OCTEON2	      0x00000100 /* Cavium Networks Octeon2.  */
+#define AFL_EXT_OCTEONP	      0x00000200 /* Cavium Networks OcteonP.  */
+#define AFL_EXT_LOONGSON_3A   0x00000400 /* Loongson 3A.  */
+#define AFL_EXT_OCTEON	      0x00000800 /* Cavium Networks Octeon.  */
+#define AFL_EXT_5900	      0x00004000 /* MIPS R5900 instruction.  */
+#define AFL_EXT_4650	      0x00010000 /* MIPS R4650 instruction.  */
+#define AFL_EXT_4010	      0x00020000 /* LSI R4010 instruction.  */
+#define AFL_EXT_4100	      0x00040000 /* NEC VR4100 instruction.  */
+#define AFL_EXT_3900	      0x00080000 /* Toshiba R3900 instruction.  */
+#define AFL_EXT_10000	      0x00100000 /* MIPS R10000 instruction.  */
+#define AFL_EXT_SB1	      0x00200000 /* Broadcom SB-1 instruction.  */
+#define AFL_EXT_4111	      0x00400000 /* NEC VR4111/VR4181 instruction.  */
+#define AFL_EXT_4120	      0x00800000 /* NEC VR4120 instruction.  */
+#define AFL_EXT_5400	      0x01000000 /* NEC VR5400 instruction.  */
+#define AFL_EXT_5500	      0x02000000 /* NEC VR5500 instruction.  */
+#define AFL_EXT_LOONGSON_2E   0x40000000 /* ST Micro Loongson 2E.  */
+#define AFL_EXT_LOONGSON_2F   0x80000000 /* ST Micro Loongson 2F.  */
+
+/* Object attribute values.  */
+enum
+{
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_MIPS_ABI_FP_ANY = 0,
+  /* Using hard-float -mdouble-float.  */
+  Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+  /* Using hard-float -msingle-float.  */
+  Val_GNU_MIPS_ABI_FP_SINGLE = 2,
+  /* Using soft-float.  */
+  Val_GNU_MIPS_ABI_FP_SOFT = 3,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
+  /* Using -mfpxx.  */
+  Val_GNU_MIPS_ABI_FP_XX = 5,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_64 = 6
+};
 
 /* HPPA specific definitions.  */
 
diff --git a/sysdeps/mips/bits/hwcap.h b/sysdeps/mips/bits/hwcap.h
new file mode 100644
index 0000000..96575d2
--- /dev/null
+++ b/sysdeps/mips/bits/hwcap.h
@@ -0,0 +1,23 @@
+/* Defines for bits in AT_HWCAP.
+   Copyright (C) 2014 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _SYS_AUXV_H
+# error "Never include <bits/hwcap.h> directly; use <sys/auxv.h> instead."
+#endif
+
+#define HWCAP_MIPS_UFR	0x00000001
diff --git a/sysdeps/mips/bits/linkmap.h b/sysdeps/mips/bits/linkmap.h
index a6df782..dfbc3be 100644
--- a/sysdeps/mips/bits/linkmap.h
+++ b/sysdeps/mips/bits/linkmap.h
@@ -1,4 +1,5 @@
 struct link_map_machine
   {
     ElfW(Addr) plt; /* Address of .plt */
+    ElfW(Word) fpmode; /* Overall FP mode */
   };
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index 5a07c0b..b10c228 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -32,6 +32,7 @@
 #include <sgidefs.h>
 #include <sys/asm.h>
 #include <dl-tls.h>
+#include <unistd.h>
 
 /* The offset of gp from GOT might be system-dependent.  It's set by
    ld.  The same value is also */
@@ -107,6 +108,223 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
     }
 }
 
+#define ELF_MACHINE_NEEDS_PHDR_CHECK
+
+static inline const ElfW(Phdr) *
+find_mips_abiflags (const ElfW(Phdr) *phdr, ElfW(Half) phnum)
+{
+  const ElfW(Phdr) *ph;
+
+  for (ph = phdr; ph < &phdr[phnum]; ++ph)
+    if (ph->p_type == PT_MIPS_ABIFLAGS)
+      return ph;
+  return NULL;
+}
+
+#if _MIPS_SIM == _ABIO32
+/* Modify the mode of the floating-point registers.  This function must not
+   be inlined as it relies on the calling-convention to only need to save
+   restore the callee-saved registers around the mode switch.  */
+
+static __attribute__ ((noinline)) void
+switch_frmode_to (int newmode)
+{
+  asm volatile
+      ("addu $sp, $sp, -48\n"
+       "sdc1 $f20, 0($sp)\n"
+       "sdc1 $f22, 8($sp)\n"
+       "sdc1 $f24, 16($sp)\n"
+       "sdc1 $f26, 24($sp)\n"
+       "sdc1 $f28, 32($sp)\n"
+       "sdc1 $f30, 40($sp)\n"
+       "beq %0, $0, 1f\n"
+       "ctc1 $0, $4\n"
+       "b 2f\n"
+       "1:\n"
+       "ctc1 $0, $1\n"
+       "2:\n"
+       "ldc1 $f20, 0($sp)\n"
+       "ldc1 $f22, 8($sp)\n"
+       "ldc1 $f24, 16($sp)\n"
+       "ldc1 $f26, 24($sp)\n"
+       "ldc1 $f28, 32($sp)\n"
+       "ldc1 $f30, 40($sp)\n"
+       "addu $sp, $sp, -48\n" :: "r"(newmode));
+}
+#endif
+
+static const char *
+mips_fp_abi (int val)
+{
+  switch (val)
+    {
+    case Val_GNU_MIPS_ABI_FP_ANY:
+      return "no float";
+    case Val_GNU_MIPS_ABI_FP_DOUBLE:
+      return "Hard float (DP)";
+    case Val_GNU_MIPS_ABI_FP_SINGLE:
+      return "Hard float (SP)";
+    case Val_GNU_MIPS_ABI_FP_SOFT:
+      return "Soft float";
+    case Val_GNU_MIPS_ABI_FP_OLD_64:
+      return "Unsupported FP64";
+    case Val_GNU_MIPS_ABI_FP_XX:
+      return "Hard float (32-bit CPU, Any FPU)";
+    case Val_GNU_MIPS_ABI_FP_64:
+      return "Hard float (32-bit CPU, 64-bit FPU)";
+    default:
+      return "Unknown FP ABI";
+    }
+}
+
+static int __attribute_used__
+elf_machine_phdr_check (const ElfW(Phdr) *phdr, ElfW(Half) phnum,
+			char * buf, int len, int fd, struct link_map * map)
+{
+  const ElfW(Phdr) *ph = find_mips_abiflags (phdr, phnum);
+  struct link_map *l;
+  Lmid_t nsid;
+  int req_abi = Val_GNU_MIPS_ABI_FP_DOUBLE;
+  Elf_ABIFlags_v0 *mips_abiflags = NULL;
+
+  /* Read the attributes section.  */
+  if (ph != NULL)
+    {
+      ElfW(Addr) size = ph->p_filesz;
+
+      if (ph->p_offset + size <= (size_t) len)
+	mips_abiflags = (Elf_ABIFlags_v0 *) (buf + ph->p_offset);
+      else
+	{
+	  mips_abiflags = alloca (size);
+	  __lseek (fd, ph->p_offset, SEEK_SET);
+	  if (__libc_read (fd, (void *) mips_abiflags, size) != size)
+	    {
+	      if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+		_dl_debug_printf ("   Unable to read PT_MIPS_ABIFLAGS\n");
+	      return 0;
+	    }
+	}
+      if (size < sizeof (Elf_ABIFlags_v0))
+	{
+	  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+	    _dl_debug_printf ("   contains malformed PT_MIPS_ABIFLAGS\n");
+	  return 0;
+	}
+      req_abi = mips_abiflags->fp_abi;
+    }
+
+  /* ANY is compatible with anything.  */
+  if (req_abi == Val_GNU_MIPS_ABI_FP_ANY)
+    return 1;
+
+  /* Check that the new mode does not conflict with any currently
+     loaded object.  */
+  for (nsid = 0; nsid < DL_NNS; ++nsid)
+    for (l = GL(dl_ns)[nsid]._ns_loaded; l != NULL; l = l->l_next)
+      {
+	bool success = true;
+	if (l->l_mach.fpmode == 0)
+	  {
+	    l->l_mach.fpmode = Val_GNU_MIPS_ABI_FP_DOUBLE;
+	    ph = find_mips_abiflags (l->l_phdr, l->l_phnum);
+	    if (ph)
+	      {
+		if (ph->p_filesz < sizeof (Elf_ABIFlags_v0))
+		  {
+		    if (__builtin_expect (GLRO(dl_debug_mask)
+					  & DL_DEBUG_LIBS, 0))
+		      _dl_debug_printf ("   malformed PT_MIPS_ABIFLAGS found\n");
+		    return 0;
+		  }
+
+		mips_abiflags = (Elf_ABIFlags_v0 *) (l->l_addr + ph->p_vaddr);
+		l->l_mach.fpmode = mips_abiflags->fp_abi;
+	      }
+	  }
+	switch (req_abi)
+	  {
+	  case Val_GNU_MIPS_ABI_FP_ANY:
+	    /* Can't happen, see above.  */
+	    break;
+	  case Val_GNU_MIPS_ABI_FP_DOUBLE:
+	    if (l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_DOUBLE
+#if _MIPS_SIM == _ABIO32
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_XX
+#endif
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_ANY)
+	      success = false;
+	    break;
+	  case Val_GNU_MIPS_ABI_FP_SINGLE:
+	    if (l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_SINGLE
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_ANY)
+	      success = false;
+	    break;
+	  case Val_GNU_MIPS_ABI_FP_SOFT:
+	    if (l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_SOFT
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_ANY)
+	      success = false;
+	    break;
+#if _MIPS_SIM == _ABIO32
+	  case Val_GNU_MIPS_ABI_FP_XX:
+	    if (l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_XX
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_DOUBLE
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_64
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_ANY)
+	      success = false;
+	    break;
+	  case Val_GNU_MIPS_ABI_FP_64:
+	    if (l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_64
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_XX
+		&& l->l_mach.fpmode != Val_GNU_MIPS_ABI_FP_ANY)
+	      success = false;
+	    break;
+#endif
+	  default:
+	    success = false;
+	  }
+
+	if (!success)
+	  {
+	    if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+	      _dl_debug_printf ("   uses %s, already loaded %s\n",
+				mips_fp_abi (req_abi),
+				mips_fp_abi (l->l_mach.fpmode));
+	    return 0;
+	  }
+      }
+
+#if _MIPS_SIM == _ABIO32
+  if (req_abi == Val_GNU_MIPS_ABI_FP_DOUBLE
+      || req_abi == Val_GNU_MIPS_ABI_FP_64)
+    {
+      if (GLRO(dl_hwcap) & HWCAP_MIPS_UFR)
+	{
+	  int status;
+	  /* Obtain UFR mode information.  */
+	  asm volatile ("cfc1 %0,$1\n": "=r"(status));
+	  if (status == 0 && req_abi == Val_GNU_MIPS_ABI_FP_64)
+	    switch_frmode_to (1);
+	  else if (status == 1 && req_abi == Val_GNU_MIPS_ABI_FP_DOUBLE)
+	    switch_frmode_to (0);
+
+	  asm volatile ("cfc1 %0,$1\n": "=r"(status));
+	  if ((status == 0 && req_abi == Val_GNU_MIPS_ABI_FP_64)
+	      || (status == 1 && req_abi == Val_GNU_MIPS_ABI_FP_DOUBLE))
+	    _dl_signal_error (0, map->l_name, NULL, "Unable to set FP mode");
+	}
+      else if (req_abi == Val_GNU_MIPS_ABI_FP_64)
+	{
+	  if (__builtin_expect (GLRO(dl_debug_mask) & DL_DEBUG_LIBS, 0))
+	    _dl_debug_printf ("   requires FR mode switch but UFR is not supported\n");
+	  return 0;
+	}
+#endif
+    }
+
+  return 1;
+}
+
 static inline ElfW(Addr) *
 elf_mips_got_from_gpreg (ElfW(Addr) gpreg)
 {
diff --git a/sysdeps/mips/dl-procinfo.c b/sysdeps/mips/dl-procinfo.c
index 4a3dbf3..6972b7c 100644
--- a/sysdeps/mips/dl-procinfo.c
+++ b/sysdeps/mips/dl-procinfo.c
@@ -59,5 +59,21 @@ PROCINFO_CLASS const char _dl_mips_platforms[4][11]
 ,
 #endif
 
+#if !defined PROCINFO_DECL && defined SHARED
+  ._dl_mips_cap_flags
+#else
+PROCINFO_CLASS const char _dl_mips_cap_flags[1][4]
+#endif
+#ifndef PROCINFO_DECL
+= {
+    "ufr"
+  }
+#endif
+#if !defined SHARED || defined PROCINFO_DECL
+;
+#else
+,
+#endif
+
 #undef PROCINFO_DECL
 #undef PROCINFO_CLASS
diff --git a/sysdeps/mips/dl-procinfo.h b/sysdeps/mips/dl-procinfo.h
index b2b7702..d50d8cf 100644
--- a/sysdeps/mips/dl-procinfo.h
+++ b/sysdeps/mips/dl-procinfo.h
@@ -50,18 +50,50 @@ _dl_string_platform (const char *str)
   return -1;
 };
 
-/* We cannot provide a general printing function.  */
-#define _dl_procinfo(type, word) -1
+#define _DL_HWCAP_COUNT	1
 
-/* There are no hardware capabilities defined.  */
-#define _dl_hwcap_string(idx) ""
+#define HWCAP_IMPORTANT         (HWCAP_MIPS_UFR)
 
-/* By default there is no important hardware capability.  */
-#define HWCAP_IMPORTANT (0)
+static inline int
+__attribute__ ((unused))
+_dl_procinfo (unsigned int type, unsigned long int word)
+{
+  int i;
+
+  /* Fallback to unknown output mechanism.  */
+  if (type == AT_HWCAP2)
+    return -1;
+
+  _dl_printf ("AT_HWCAP:   ");
+
+  for (i = 0; i < _DL_HWCAP_COUNT; ++i)
+    if (word & (1 << i))
+      _dl_printf (" %s", GLRO(dl_mips_cap_flags)[i]);
+
+  _dl_printf ("\n");
+
+  return 0;
+}
+
+static inline const char *
+__attribute__ ((unused))
+_dl_hwcap_string (int idx)
+{
+  return GLRO(dl_mips_cap_flags)[idx];
+};
 
-/* We don't have any hardware capabilities.  */
-#define _DL_HWCAP_COUNT	0
+static inline int
+__attribute__ ((unused))
+_dl_string_hwcap (const char *str)
+{
+  int i;
 
-#define _dl_string_hwcap(str) (-1)
+  for (i = 0; i < _DL_HWCAP_COUNT; i++)
+    {
+      if (strcmp (str, GLRO(dl_mips_cap_flags)[i]) == 0)
+	return i;
+    }
+  return -1;
+};
 
 #endif /* dl-procinfo.h */
diff --git a/sysdeps/unix/mips/sysdep.h b/sysdeps/unix/mips/sysdep.h
index d59fac0..7c930ef 100644
--- a/sysdeps/unix/mips/sysdep.h
+++ b/sysdeps/unix/mips/sysdep.h
@@ -19,6 +19,9 @@
 #include <sgidefs.h>
 #include <sysdeps/unix/sysdep.h>
 
+#define _SYS_AUXV_H 1
+#include <bits/hwcap.h>
+
 #ifdef __ASSEMBLER__
 
 #include <regdef.h>
diff --git a/sysdeps/unix/sysv/linux/mips/configure b/sysdeps/unix/sysv/linux/mips/configure
index e8b0d7b..db6c8ff 100644
--- a/sysdeps/unix/sysv/linux/mips/configure
+++ b/sysdeps/unix/sysv/linux/mips/configure
@@ -268,6 +268,33 @@ fi
 config_vars="$config_vars
 default-abi = ${libc_mips_abi}_${libc_mips_float}${libc_mips_nan}"
 
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for .module fp=xx support" >&5
+$as_echo_n "checking for .module fp=xx support... " >&6; }
+if ${libc_cv_asm_module_fpxx_directive+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat > conftest.s <<EOF
+.module fp=xx
+EOF
+if { ac_try='${CC-cc} -c $ASFLAGS conftest.s 1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }; then
+  libc_cv_asm_module_fpxx_directive=yes
+else
+  libc_cv_asm_module_fpxx_directive=no
+fi
+rm -f conftest*
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_asm_module_fpxx_directive" >&5
+$as_echo "$libc_cv_asm_module_fpxx_directive" >&6; }
+if test $libc_cv_asm_module_fpxx_directive = yes; then
+  $as_echo "#define HAVE_MIPS_MODULE_FPXX_DIRECTIVE 1" >>confdefs.h
+
+fi
+
 case "$prefix" in
 /usr | /usr/)
   # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
diff --git a/sysdeps/unix/sysv/linux/mips/configure.ac b/sysdeps/unix/sysv/linux/mips/configure.ac
index 7087a14..cef2666 100644
--- a/sysdeps/unix/sysv/linux/mips/configure.ac
+++ b/sysdeps/unix/sysv/linux/mips/configure.ac
@@ -58,6 +58,21 @@ fi
 LIBC_CONFIG_VAR([default-abi],
   [${libc_mips_abi}_${libc_mips_float}${libc_mips_nan}])
 
+AC_CACHE_CHECK(for .module fp=xx support,
+               libc_cv_asm_module_fpxx_directive, [dnl
+cat > conftest.s <<EOF
+.module fp=xx
+EOF
+if AC_TRY_COMMAND(${CC-cc} -c $ASFLAGS conftest.s 1>&AS_MESSAGE_LOG_FD); then
+  libc_cv_asm_module_fpxx_directive=yes
+else
+  libc_cv_asm_module_fpxx_directive=no
+fi
+rm -f conftest*])
+if test $libc_cv_asm_module_fpxx_directive = yes; then
+  AC_DEFINE(HAVE_MIPS_MODULE_FPXX_DIRECTIVE)
+fi
+
 case "$prefix" in
 /usr | /usr/)
   # 64-bit libraries on bi-arch platforms go in /lib64 instead of /lib.
diff --git a/sysdeps/unix/sysv/linux/mips/getcontext.S b/sysdeps/unix/sysv/linux/mips/getcontext.S
index 1e0a277..14e7448 100644
--- a/sysdeps/unix/sysv/linux/mips/getcontext.S
+++ b/sysdeps/unix/sysv/linux/mips/getcontext.S
@@ -17,6 +17,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <config.h>
+#if HAVE_MIPS_MODULE_FPXX_DIRECTIVE
+	.module fp=xx
+#endif
 #include <sysdep.h>
 #include <sys/asm.h>
 #include <sys/fpregdef.h>
diff --git a/sysdeps/unix/sysv/linux/mips/setcontext.S b/sysdeps/unix/sysv/linux/mips/setcontext.S
index beeb2a5..217590c 100644
--- a/sysdeps/unix/sysv/linux/mips/setcontext.S
+++ b/sysdeps/unix/sysv/linux/mips/setcontext.S
@@ -17,6 +17,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <config.h>
+#if HAVE_MIPS_MODULE_FPXX_DIRECTIVE
+	.module fp=xx
+#endif
 #include <sysdep.h>
 #include <sys/asm.h>
 #include <sys/fpregdef.h>
diff --git a/sysdeps/unix/sysv/linux/mips/swapcontext.S b/sysdeps/unix/sysv/linux/mips/swapcontext.S
index 2a79976..1989e57 100644
--- a/sysdeps/unix/sysv/linux/mips/swapcontext.S
+++ b/sysdeps/unix/sysv/linux/mips/swapcontext.S
@@ -17,6 +17,10 @@
    License along with the GNU C Library.  If not, see
    <http://www.gnu.org/licenses/>.  */
 
+#include <config.h>
+#if HAVE_MIPS_MODULE_FPXX_DIRECTIVE
+	.module fp=xx
+#endif
 #include <sysdep.h>
 #include <sys/asm.h>
 #include <sys/fpregdef.h>
