Merge "Cache negative DNS results."
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 9d3badc..e2713db 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -58,34 +58,34 @@
 extern const char* const sys_signame[];
 
 static __inline__ int sigismember(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  return (int) ((local_set[signum/LONG_BIT] >> (signum%LONG_BIT)) & 1);
+  return (int) ((local_set[bit / LONG_BIT] >> (bit % LONG_BIT)) & 1);
 }
 
 static __inline__ int sigaddset(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  local_set[signum/LONG_BIT] |= 1UL << (signum%LONG_BIT);
+  local_set[bit / LONG_BIT] |= 1UL << (bit % LONG_BIT);
   return 0;
 }
 
 static __inline__ int sigdelset(sigset_t* set, int signum) {
-  if (set == NULL || signum < 1 || signum >= 8*sizeof(sigset_t)) {
+  int bit = signum - 1; // Signal numbers start at 1, but bit positions start at 0.
+  if (set == NULL || bit < 0 || bit >= 8*sizeof(sigset_t)) {
     errno = EINVAL;
     return -1;
   }
   unsigned long* local_set = (unsigned long*) set;
-  signum--;
-  local_set[signum/LONG_BIT] &= ~(1UL << (signum%LONG_BIT));
+  local_set[bit / LONG_BIT] &= ~(1UL << (bit % LONG_BIT));
   return 0;
 }
 
diff --git a/libm/include/mips/fenv.h b/libm/include/mips/fenv.h
index da7e696..ed69cf8 100644
--- a/libm/include/mips/fenv.h
+++ b/libm/include/mips/fenv.h
@@ -26,193 +26,200 @@
  * $FreeBSD: src/lib/msun/arm/fenv.h,v 1.5 2005/03/16 19:03:45 das Exp $
  */
 
-#ifndef	_FENV_H_
-#define	_FENV_H_
+/*
+   Rewritten for Android.
+*/
+
+/* MIPS FPU floating point control register bits.
+ *
+ * 31-25  -> floating point conditions code bits set by FP compare
+ *           instructions
+ * 24     -> flush denormalized results to zero instead of
+ *           causing unimplemented operation exception.
+ * 23     -> Condition bit
+ * 22     -> In conjunction with FS detects denormalized
+ *           operands and replaces them internally with 0.
+ * 21     -> In conjunction with FS forces denormalized operands
+ *           to the closest normalized value.
+ * 20-18  -> reserved (read as 0, write with 0)
+ * 17     -> cause bit for unimplemented operation
+ * 16     -> cause bit for invalid exception
+ * 15     -> cause bit for division by zero exception
+ * 14     -> cause bit for overflow exception
+ * 13     -> cause bit for underflow exception
+ * 12     -> cause bit for inexact exception
+ * 11     -> enable exception for invalid exception
+ * 10     -> enable exception for division by zero exception
+ *  9     -> enable exception for overflow exception
+ *  8     -> enable exception for underflow exception
+ *  7     -> enable exception for inexact exception
+ *  6     -> flag invalid exception
+ *  5     -> flag division by zero exception
+ *  4     -> flag overflow exception
+ *  3     -> flag underflow exception
+ *  2     -> flag inexact exception
+ *  1-0   -> rounding control
+ *
+ *
+ * Rounding Control:
+ * 00 - rounding to nearest (RN)
+ * 01 - rounding toward zero (RZ)
+ * 10 - rounding (up) toward plus infinity (RP)
+ * 11 - rounding (down)toward minus infinity (RM)
+ */
+
+#ifndef _FENV_H_
+#define _FENV_H_
 
 #include <sys/types.h>
 
 __BEGIN_DECLS
 
-typedef	__uint32_t	fenv_t;
-typedef	__uint32_t	fexcept_t;
+typedef __uint32_t    fenv_t;
+typedef __uint32_t    fexcept_t;
 
 /* Exception flags */
-#define	FE_INVALID	0x0001
-#define	FE_DIVBYZERO	0x0002
-#define	FE_OVERFLOW	0x0004
-#define	FE_UNDERFLOW	0x0008
-#define	FE_INEXACT	0x0010
-#define	FE_ALL_EXCEPT	(FE_DIVBYZERO | FE_INEXACT | \
-			 FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define FE_INVALID      0x40
+#define FE_DIVBYZERO    0x20
+#define FE_OVERFLOW     0x10
+#define FE_UNDERFLOW    0x08
+#define FE_INEXACT      0x04
+#define FE_ALL_EXCEPT   (FE_DIVBYZERO | FE_INEXACT | \
+                         FE_INVALID | FE_OVERFLOW | FE_UNDERFLOW)
+#define _FCSR_CAUSE_SHIFT  10
+#define _ENABLE_SHIFT 5
+#define _FCSR_ENABLE_MASK (FE_ALL_EXCEPT << _ENABLE_SHIFT)
 
 /* Rounding modes */
-#define	FE_TONEAREST	0x0000
-#define	FE_TOWARDZERO	0x0001
-#define	FE_UPWARD	0x0002
-#define	FE_DOWNWARD	0x0003
-#define	_ROUND_MASK	(FE_TONEAREST | FE_DOWNWARD | \
-			 FE_UPWARD | FE_TOWARDZERO)
-
+#define FE_TONEAREST    0x0000
+#define FE_TOWARDZERO   0x0001
+#define FE_UPWARD       0x0002
+#define FE_DOWNWARD     0x0003
+#define _FCSR_RMODE_SHIFT 0
+#define _FCSR_RMASK       0x3
 /* Default floating-point environment */
-extern const fenv_t	__fe_dfl_env;
-#define	FE_DFL_ENV	(&__fe_dfl_env)
+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)
-
-#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)
+static __inline int fegetenv(fenv_t* __envp) {
+   fenv_t _fcsr = 0;
+#ifdef  __mips_hard_float
+   __asm__ __volatile__("cfc1 %0,$31" : "=r" (_fcsr));
 #endif
-
-static __inline int
-feclearexcept(int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__fpsr &= ~__excepts;
-	__wfs(__fpsr);
-	return (0);
+   *__envp = _fcsr;
+   return 0;
 }
 
-static __inline int
-fegetexceptflag(fexcept_t *__flagp, int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	*__flagp = __fpsr & __excepts;
-	return (0);
+static __inline int fesetenv(const fenv_t* __envp) {
+  fenv_t _fcsr = *__envp;
+#ifdef  __mips_hard_float
+  __asm__ __volatile__("ctc1 %0,$31" : : "r" (_fcsr));
+#endif
+  return 0;
 }
 
-static __inline int
-fesetexceptflag(const fexcept_t *__flagp, int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__fpsr &= ~__excepts;
-	__fpsr |= *__flagp & __excepts;
-	__wfs(__fpsr);
-	return (0);
+static __inline int feclearexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~(__excepts | (__excepts << _FCSR_CAUSE_SHIFT));
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-feraiseexcept(int __excepts)
-{
-	fexcept_t __ex = __excepts;
-
-	fesetexceptflag(&__ex, __excepts);	/* XXX */
-	return (0);
+static __inline int fegetexceptflag(fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  *__flagp = __fcsr & __excepts & FE_ALL_EXCEPT;
+  return 0;
 }
 
-static __inline int
-fetestexcept(int __excepts)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	return (__fpsr & __excepts);
+static __inline int fesetexceptflag(const fexcept_t* __flagp, int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  __fcsr &= ~__excepts;
+  __fcsr |= *__flagp & __excepts;
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-fegetround(void)
-{
-
-	/*
-	 * 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);
+static __inline int feraiseexcept(int __excepts) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  /* Ensure that flags are all legal */
+  __excepts &= FE_ALL_EXCEPT;
+  /* Cause bit needs to be set as well for generating the exception*/
+  __fcsr |= __excepts | (__excepts << _FCSR_CAUSE_SHIFT);
+  fesetenv(&__fcsr);
+  return 0;
 }
 
-static __inline int
-fesetround(int __round)
-{
-
-	return (-1);
+static __inline int fetestexcept(int __excepts) {
+  fexcept_t __FCSR;
+  fegetenv(&__FCSR);
+  return (__FCSR & __excepts & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fegetenv(fenv_t *__envp)
-{
-
-	__rfs(__envp);
-	return (0);
+static __inline int fegetround(void) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  return (_fcsr & _FCSR_RMASK);
 }
 
-static __inline int
-feholdexcept(fenv_t *__envp)
-{
-	fenv_t __env;
-
-	__rfs(&__env);
-	*__envp = __env;
-	__env &= ~(FE_ALL_EXCEPT | _ENABLE_MASK);
-	__wfs(__env);
-	return (0);
+static __inline int fesetround(int __round) {
+  fenv_t _fcsr;
+  fegetenv(&_fcsr);
+  _fcsr &= ~_FCSR_RMASK;
+  _fcsr |= (__round & _FCSR_RMASK ) ;
+  fesetenv(&_fcsr);
+  return 0;
 }
 
-static __inline int
-fesetenv(const fenv_t *__envp)
-{
-
-	__wfs(*__envp);
-	return (0);
+static __inline int feholdexcept(fenv_t* __envp) {
+  fenv_t __env;
+  fegetenv(&__env);
+  *__envp = __env;
+  __env &= ~(FE_ALL_EXCEPT | _FCSR_ENABLE_MASK);
+  fesetenv(&__env);
+  return 0;
 }
 
-static __inline int
-feupdateenv(const fenv_t *__envp)
-{
-	fexcept_t __fpsr;
-
-	__rfs(&__fpsr);
-	__wfs(*__envp);
-	feraiseexcept(__fpsr & FE_ALL_EXCEPT);
-	return (0);
+static __inline int feupdateenv(const fenv_t* __envp) {
+  fexcept_t __fcsr;
+  fegetenv(&__fcsr);
+  fesetenv(__envp);
+  feraiseexcept(__fcsr & FE_ALL_EXCEPT);
+  return 0;
 }
 
 #if __BSD_VISIBLE
 
-static __inline int
-feenableexcept(int __mask)
-{
-	fenv_t __old_fpsr, __new_fpsr;
-
-	__rfs(&__old_fpsr);
-	__new_fpsr = __old_fpsr | (__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT;
-	__wfs(__new_fpsr);
-	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+static __inline int feenableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr | (__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT;
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fedisableexcept(int __mask)
-{
-	fenv_t __old_fpsr, __new_fpsr;
-
-	__rfs(&__old_fpsr);
-	__new_fpsr = __old_fpsr & ~((__mask & FE_ALL_EXCEPT) << _FPUSW_SHIFT);
-	__wfs(__new_fpsr);
-	return ((__old_fpsr >> _FPUSW_SHIFT) & FE_ALL_EXCEPT);
+static __inline int fedisableexcept(int __mask) {
+  fenv_t __old_fcsr, __new_fcsr;
+  fegetenv(&__old_fcsr);
+  __new_fcsr = __old_fcsr & ~((__mask & FE_ALL_EXCEPT) << _ENABLE_SHIFT);
+  fesetenv(&__new_fcsr);
+  return ((__old_fcsr >> _ENABLE_SHIFT) & FE_ALL_EXCEPT);
 }
 
-static __inline int
-fegetexcept(void)
-{
-	fenv_t __fpsr;
-
-	__rfs(&__fpsr);
-	return ((__fpsr & _ENABLE_MASK) >> _FPUSW_SHIFT);
+static __inline int fegetexcept(void) {
+  fenv_t __fcsr;
+  fegetenv(&__fcsr);
+  return ((__fcsr & _FCSR_ENABLE_MASK) >> _ENABLE_SHIFT);
 }
 
 #endif /* __BSD_VISIBLE */
 
 __END_DECLS
 
-#endif	/* !_FENV_H_ */
+#endif /* !_FENV_H_ */
diff --git a/tests/Android.mk b/tests/Android.mk
index 083bb70..a50232e 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -98,13 +98,15 @@
 # -----------------------------------------------------------------------------
 
 # Build no-elf-hash-table-library.so to test dlopen(3) on a library that
-# only has a GNU-style hash table.
+# only has a GNU-style hash table. MIPS doesn't support GNU hash style.
+ifneq ($(TARGET_ARCH),mips)
 include $(CLEAR_VARS)
 LOCAL_MODULE := no-elf-hash-table-library
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_SRC_FILES := empty.cpp
 LOCAL_LDFLAGS := -Wl,--hash-style=gnu
 include $(BUILD_SHARED_LIBRARY)
+endif
 
 # -----------------------------------------------------------------------------
 # Unit tests built against glibc.
diff --git a/tests/dlfcn_test.cpp b/tests/dlfcn_test.cpp
index 0c40eb7..938b8a5 100644
--- a/tests/dlfcn_test.cpp
+++ b/tests/dlfcn_test.cpp
@@ -188,8 +188,11 @@
   ASSERT_TRUE(dlerror() == NULL); // dladdr(3) doesn't set dlerror(3).
 }
 
-#if __BIONIC__
 // Our dynamic linker doesn't support GNU hash tables.
+#if defined(__BIONIC__)
+// GNU-style ELF hash tables are incompatible with the MIPS ABI.
+// MIPS requires .dynsym to be sorted to match the GOT but GNU-style requires sorting by hash code.
+#if !defined(__mips__)
 TEST(dlfcn, dlopen_library_with_only_gnu_hash) {
   dlerror(); // Clear any pending errors.
   void* handle = dlopen("no-elf-hash-table-library.so", RTLD_NOW);
@@ -197,6 +200,7 @@
   ASSERT_STREQ("dlopen failed: empty/missing DT_HASH in \"no-elf-hash-table-library.so\" (built with --hash-style=gnu?)", dlerror());
 }
 #endif
+#endif
 
 TEST(dlfcn, dlopen_bad_flags) {
   dlerror(); // Clear any pending errors.
diff --git a/tests/signal_test.cpp b/tests/signal_test.cpp
index fcfcb18..1292568 100644
--- a/tests/signal_test.cpp
+++ b/tests/signal_test.cpp
@@ -48,13 +48,13 @@
   int min_signal = SIGHUP;
   int max_signal = SIGRTMAX;
 
-#if __BIONIC__
-  // bionic's sigset_t is too small: 32 bits instead of 64.
+#if defined(__BIONIC__) && !defined(__mips__)
+  // bionic's sigset_t is too small for ARM and x86: 32 bits instead of 64.
   // This means you can't refer to any of the real-time signals.
   // See http://b/3038348 and http://b/5828899.
-  max_signal = 31;
+  max_signal = 32;
 #else
-  // Other C libraries are perfectly capable of using their largest signal.
+  // Other C libraries (or bionic for MIPS) are perfectly capable of using their largest signal.
   ASSERT_GE(sizeof(sigset_t) * 8, static_cast<size_t>(SIGRTMAX));
 #endif