Bug 1194139 - IonMonkey: MIPS: Split shareable code to mips-shared in Architecture-mips32. r=nbp
authorHeiher <r@hev.cc>
Thu, 20 Aug 2015 00:02:00 -0400
changeset 292399 fdaacec0f5a14916797c1de54a02f166ac666bdf
parent 292398 9edc2be6aa22a23adbe719876f500ea72ee0df1c
child 292400 3b900efecde6c2d61a667df20b2d9ca33d684044
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnbp
bugs1194139
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1194139 - IonMonkey: MIPS: Split shareable code to mips-shared in Architecture-mips32. r=nbp
js/src/jit/mips-shared/Architecture-mips.cpp
js/src/jit/mips-shared/Architecture-mips.h
js/src/jit/mips32/Architecture-mips32.cpp
js/src/jit/mips32/Architecture-mips32.h
js/src/moz.build
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips-shared/Architecture-mips.cpp
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "jit/mips-shared/Architecture-mips.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "jit/RegisterSets.h"
+
+#define HWCAP_MIPS (1 << 31)
+#define HWCAP_FPU (1 << 0)
+
+namespace js {
+namespace jit {
+
+uint32_t GetMIPSFlags()
+{
+    static bool isSet = false;
+    static uint32_t flags = 0;
+    if (isSet)
+        return flags;
+#ifdef JS_SIMULATOR_MIPS32
+    isSet = true;
+    flags |= HWCAP_FPU;
+    return flags;
+#else
+
+#ifdef __linux__
+    FILE* fp = fopen("/proc/cpuinfo", "r");
+    if (!fp)
+        return false;
+
+    char buf[1024];
+    memset(buf, 0, sizeof(buf));
+    fread(buf, sizeof(char), sizeof(buf) - 1, fp);
+    fclose(fp);
+    if (strstr(buf, "FPU"))
+        flags |= HWCAP_FPU;
+
+    isSet = true;
+    return flags;
+#endif
+
+    return flags;
+#endif // JS_SIMULATOR_MIPS32
+}
+
+bool hasFPU()
+{
+    return js::jit::GetMIPSFlags() & HWCAP_FPU;
+}
+
+Registers::Code
+Registers::FromName(const char* name)
+{
+    for (size_t i = 0; i < Total; i++) {
+        if (strcmp(GetName(i), name) == 0)
+            return Code(i);
+    }
+
+    return Invalid;
+}
+
+} // namespace ion
+} // namespace js
+
new file mode 100644
--- /dev/null
+++ b/js/src/jit/mips-shared/Architecture-mips.h
@@ -0,0 +1,314 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef jit_mips_shared_Architecture_mips_h
+#define jit_mips_shared_Architecture_mips_h
+
+#include "mozilla/MathAlgorithms.h"
+
+#include <limits.h>
+#include <stdint.h>
+
+#include "js/Utility.h"
+
+// gcc appears to use _mips_hard_float to denote
+// that the target is a hard-float target.
+#ifdef _mips_hard_float
+#define JS_CODEGEN_MIPS32_HARDFP
+#endif
+
+#if _MIPS_SIM == _ABIO32
+#define USES_O32_ABI
+#else
+#error "Unsupported ABI"
+#endif
+
+namespace js {
+namespace jit {
+
+class Registers
+{
+  public:
+    enum RegisterID {
+        r0 = 0,
+        r1,
+        r2,
+        r3,
+        r4,
+        r5,
+        r6,
+        r7,
+        r8,
+        r9,
+        r10,
+        r11,
+        r12,
+        r13,
+        r14,
+        r15,
+        r16,
+        r17,
+        r18,
+        r19,
+        r20,
+        r21,
+        r22,
+        r23,
+        r24,
+        r25,
+        r26,
+        r27,
+        r28,
+        r29,
+        r30,
+        r31,
+        zero = r0,
+        at = r1,
+        v0 = r2,
+        v1 = r3,
+        a0 = r4,
+        a1 = r5,
+        a2 = r6,
+        a3 = r7,
+        t0 = r8,
+        t1 = r9,
+        t2 = r10,
+        t3 = r11,
+        t4 = r12,
+        t5 = r13,
+        t6 = r14,
+        t7 = r15,
+        s0 = r16,
+        s1 = r17,
+        s2 = r18,
+        s3 = r19,
+        s4 = r20,
+        s5 = r21,
+        s6 = r22,
+        s7 = r23,
+        t8 = r24,
+        t9 = r25,
+        k0 = r26,
+        k1 = r27,
+        gp = r28,
+        sp = r29,
+        fp = r30,
+        ra = r31,
+        invalid_reg
+    };
+    typedef uint8_t Code;
+    typedef RegisterID Encoding;
+
+    // Content spilled during bailouts.
+    union RegisterContent {
+        uintptr_t r;
+    };
+
+    static const char* GetName(Code code) {
+        MOZ_ASSERT(code < Total);
+        static const char * const Names[] = REGISTERS_NAMES;
+        return Names[code];
+    }
+    static const char* GetName(Encoding i) {
+        return GetName(Code(i));
+    }
+
+    static Code FromName(const char* name);
+
+    static const Encoding StackPointer = sp;
+    static const Encoding Invalid = invalid_reg;
+
+    static const uint32_t Total = 32;
+    static const uint32_t Allocatable = REGISTERS_ALLOCATABLE;
+
+    typedef uint32_t SetType;
+    static const SetType AllMask = 0xffffffff;
+    static const SetType SharedArgRegMask = (1 << a0) | (1 << a1) | (1 << a2) | (1 << a3);
+    static const SetType ArgRegMask = REGISTERS_ARGREGMASK;
+
+    static const SetType VolatileMask =
+        (1 << Registers::v0) |
+        (1 << Registers::v1) |
+        (1 << Registers::a0) |
+        (1 << Registers::a1) |
+        (1 << Registers::a2) |
+        (1 << Registers::a3) |
+        (1 << Registers::t0) |
+        (1 << Registers::t1) |
+        (1 << Registers::t2) |
+        (1 << Registers::t3) |
+        (1 << Registers::t4) |
+        (1 << Registers::t5) |
+        (1 << Registers::t6) |
+        (1 << Registers::t7);
+
+    // We use this constant to save registers when entering functions. This
+    // is why $ra is added here even though it is not "Non Volatile".
+    static const SetType NonVolatileMask =
+        (1 << Registers::s0) |
+        (1 << Registers::s1) |
+        (1 << Registers::s2) |
+        (1 << Registers::s3) |
+        (1 << Registers::s4) |
+        (1 << Registers::s5) |
+        (1 << Registers::s6) |
+        (1 << Registers::s7) |
+        (1 << Registers::ra);
+
+    static const SetType WrapperMask =
+        VolatileMask |         // = arguments
+        (1 << Registers::t0) | // = outReg
+        (1 << Registers::t1);  // = argBase
+
+    static const SetType NonAllocatableMask =
+        (1 << Registers::zero) |
+        (1 << Registers::at) | // at = scratch
+        (1 << Registers::t8) | // t8 = scratch
+        (1 << Registers::t9) | // t9 = scratch
+        (1 << Registers::k0) |
+        (1 << Registers::k1) |
+        (1 << Registers::gp) |
+        (1 << Registers::sp) |
+        (1 << Registers::fp) |
+        (1 << Registers::ra);
+
+    // Registers that can be allocated without being saved, generally.
+    static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
+
+    // Registers returned from a JS -> JS call.
+    static const SetType JSCallMask = REGISTERS_JSCALLMASK;
+
+    // Registers returned from a JS -> C call.
+    static const SetType SharedCallMask = (1 << Registers::v0);
+    static const SetType CallMask = REGISTERS_CALLMASK;
+
+    static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
+
+    static uint32_t SetSize(SetType x) {
+        static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
+        return mozilla::CountPopulation32(x);
+    }
+    static uint32_t FirstBit(SetType x) {
+        return mozilla::CountTrailingZeroes32(x);
+    }
+    static uint32_t LastBit(SetType x) {
+        return 31 - mozilla::CountLeadingZeroes32(x);
+    }
+};
+
+// Smallest integer type that can hold a register bitmask.
+typedef uint32_t PackedRegisterMask;
+
+class BaseFloatRegisters
+{
+  public:
+    enum FPRegisterID {
+        f0 = 0,
+        f1,
+        f2,
+        f3,
+        f4,
+        f5,
+        f6,
+        f7,
+        f8,
+        f9,
+        f10,
+        f11,
+        f12,
+        f13,
+        f14,
+        f15,
+        f16,
+        f17,
+        f18,
+        f19,
+        f20,
+        f21,
+        f22,
+        f23,
+        f24,
+        f25,
+        f26,
+        f27,
+        f28,
+        f29,
+        f30,
+        f31,
+        invalid_freg
+    };
+    typedef FPRegisterID Code;
+    typedef FPRegisterID Encoding;
+
+    // Content spilled during bailouts.
+    union RegisterContent {
+        double d;
+    };
+
+    static const char* GetName(Code code) {
+        static const char * const Names[] = { "f0", "f1", "f2", "f3",  "f4", "f5",  "f6", "f7",
+                                              "f8", "f9",  "f10", "f11", "f12", "f13",
+                                              "f14", "f15", "f16", "f17", "f18", "f19",
+                                              "f20", "f21", "f22", "f23", "f24", "f25",
+                                              "f26", "f27", "f28", "f29", "f30", "f31"};
+        return Names[code];
+    }
+
+    static const Code Invalid = invalid_freg;
+
+    typedef uint64_t SetType;
+};
+
+template <typename T>
+class TypedRegisterSet;
+
+class BaseFloatRegister
+{
+  public:
+    bool isInt32x4() const { return false; }
+    bool isFloat32x4() const { return false; }
+
+    typedef BaseFloatRegisters::SetType SetType;
+
+    static uint32_t SetSize(SetType x) {
+        static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
+        return mozilla::CountPopulation32(x);
+    }
+    static uint32_t FirstBit(SetType x) {
+        return mozilla::CountTrailingZeroes64(x);
+    }
+    static uint32_t LastBit(SetType x) {
+        return 63 - mozilla::CountLeadingZeroes64(x);
+    }
+};
+
+uint32_t GetMIPSFlags();
+bool hasFPU();
+
+// MIPS doesn't have double registers that can NOT be treated as float32.
+inline bool
+hasUnaliasedDouble() {
+    return false;
+}
+
+// On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need
+// to convert a float32 to a double as a temporary, you need a temporary
+// double register.
+inline bool
+hasMultiAlias() {
+    return true;
+}
+
+// See the comments above AsmJSMappedSize in AsmJSValidate.h for more info.
+// TODO: Implement this for MIPS. Note that it requires Codegen to respect the
+// offset field of AsmJSHeapAccess.
+static const size_t AsmJSCheckedImmediateRange = 0;
+static const size_t AsmJSImmediateRange = 0;
+
+} // namespace jit
+} // namespace js
+
+#endif /* jit_mips_shared_Architecture_mips_h */
--- a/js/src/jit/mips32/Architecture-mips32.cpp
+++ b/js/src/jit/mips32/Architecture-mips32.cpp
@@ -1,75 +1,21 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "jit/mips32/Architecture-mips32.h"
 
-#include <fcntl.h>
-#include <unistd.h>
-
 #include "jit/RegisterSets.h"
 
-#define HWCAP_MIPS (1 << 31)
-#define HWCAP_FPU (1 << 0)
-
 namespace js {
 namespace jit {
 
-uint32_t GetMIPSFlags()
-{
-    static bool isSet = false;
-    static uint32_t flags = 0;
-    if (isSet)
-        return flags;
-#ifdef JS_SIMULATOR_MIPS32
-    isSet = true;
-    flags |= HWCAP_FPU;
-    return flags;
-#else
-
-#ifdef __linux__
-    FILE* fp = fopen("/proc/cpuinfo", "r");
-    if (!fp)
-        return false;
-
-    char buf[1024];
-    memset(buf, 0, sizeof(buf));
-    fread(buf, sizeof(char), sizeof(buf) - 1, fp);
-    fclose(fp);
-    if (strstr(buf, "FPU"))
-        flags |= HWCAP_FPU;
-
-    isSet = true;
-    return flags;
-#endif
-
-    return false;
-#endif // JS_SIMULATOR_MIPS32
-}
-
-bool hasFPU()
-{
-    return js::jit::GetMIPSFlags() & HWCAP_FPU;
-}
-
-Registers::Code
-Registers::FromName(const char* name)
-{
-    for (size_t i = 0; i < Total; i++) {
-        if (strcmp(GetName(i), name) == 0)
-            return Code(i);
-    }
-
-    return Invalid;
-}
-
 FloatRegisters::Code
 FloatRegisters::FromName(const char* name)
 {
     for (size_t i = 0; i < Total; i++) {
         if (strcmp(GetName(i), name) == 0)
             return Code(i);
     }
 
--- a/js/src/jit/mips32/Architecture-mips32.h
+++ b/js/src/jit/mips32/Architecture-mips32.h
@@ -9,27 +9,34 @@
 
 #include "mozilla/MathAlgorithms.h"
 
 #include <limits.h>
 #include <stdint.h>
 
 #include "js/Utility.h"
 
-// gcc appears to use _mips_hard_float to denote
-// that the target is a hard-float target.
-#ifdef _mips_hard_float
-#define JS_CODEGEN_MIPS32_HARDFP
-#endif
+#define REGISTERS_NAMES         \
+    { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3", \
+      "t0",   "t1", "t2", "t3", "t4", "t5", "t6", "t7", \
+      "s0",   "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+      "t8",   "t9", "k0", "k1", "gp", "sp", "fp", "ra"};
+
+#define REGISTERS_ALLOCATABLE   14
+#define REGISTERS_ARGREGMASK    SharedArgRegMask
 
-#if _MIPS_SIM == _ABIO32
-#define USES_O32_ABI
-#else
-#error "Unsupported ABI"
-#endif
+#define REGISTERS_JSCALLMASK    \
+    (1 << Registers::a2) |      \
+    (1 << Registers::a3);
+
+#define REGISTERS_CALLMASK      \
+    (1 << Registers::v0) |      \
+    (1 << Registers::v1);  // used for double-size returns
+
+#include "jit/mips-shared/Architecture-mips.h"
 
 namespace js {
 namespace jit {
 
 // Shadow stack space is not required on MIPS.
 static const uint32_t ShadowStackSpace = 4 * sizeof(uintptr_t);
 
 // These offsets are specific to nunboxing, and capture offsets into the
@@ -37,276 +44,46 @@ static const uint32_t ShadowStackSpace =
 // Size of MIPS32 general purpose registers is 32 bits.
 static const int32_t NUNBOX32_TYPE_OFFSET = 4;
 static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0;
 
 // Size of each bailout table entry.
 // For MIPS this is 2 instructions relative call.
 static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void*);
 
-class Registers
-{
-  public:
-    enum RegisterID {
-        r0 = 0,
-        r1,
-        r2,
-        r3,
-        r4,
-        r5,
-        r6,
-        r7,
-        r8,
-        r9,
-        r10,
-        r11,
-        r12,
-        r13,
-        r14,
-        r15,
-        r16,
-        r17,
-        r18,
-        r19,
-        r20,
-        r21,
-        r22,
-        r23,
-        r24,
-        r25,
-        r26,
-        r27,
-        r28,
-        r29,
-        r30,
-        r31,
-        zero = r0,
-        at = r1,
-        v0 = r2,
-        v1 = r3,
-        a0 = r4,
-        a1 = r5,
-        a2 = r6,
-        a3 = r7,
-        t0 = r8,
-        t1 = r9,
-        t2 = r10,
-        t3 = r11,
-        t4 = r12,
-        t5 = r13,
-        t6 = r14,
-        t7 = r15,
-        s0 = r16,
-        s1 = r17,
-        s2 = r18,
-        s3 = r19,
-        s4 = r20,
-        s5 = r21,
-        s6 = r22,
-        s7 = r23,
-        t8 = r24,
-        t9 = r25,
-        k0 = r26,
-        k1 = r27,
-        gp = r28,
-        sp = r29,
-        fp = r30,
-        ra = r31,
-        invalid_reg
-    };
-    typedef uint8_t Code;
-    typedef RegisterID Encoding;
-
-    // Content spilled during bailouts.
-    union RegisterContent {
-        uintptr_t r;
-    };
-
-    static const char* GetName(Code code) {
-        MOZ_ASSERT(code < Total);
-        static const char * const Names[] = { "zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
-                                              "t0",   "t1", "t2", "t3", "t4", "t5", "t6", "t7",
-                                              "s0",   "s1", "s2", "s3", "s4", "s5", "s6", "s7",
-                                              "t8",   "t9", "k0", "k1", "gp", "sp", "fp", "ra"};
-        return Names[code];
-    }
-    static const char* GetName(Encoding i) {
-        return GetName(Code(i));
-    }
-
-    static Code FromName(const char* name);
-
-    static const Encoding StackPointer = sp;
-    static const Encoding Invalid = invalid_reg;
-
-    static const uint32_t Total = 32;
-    static const uint32_t Allocatable = 14;
-
-    typedef uint32_t SetType;
-    static const SetType AllMask = 0xffffffff;
-    static const SetType ArgRegMask = (1 << a0) | (1 << a1) | (1 << a2) | (1 << a3);
-
-    static const SetType VolatileMask =
-        (1 << Registers::v0) |
-        (1 << Registers::v1) |
-        (1 << Registers::a0) |
-        (1 << Registers::a1) |
-        (1 << Registers::a2) |
-        (1 << Registers::a3) |
-        (1 << Registers::t0) |
-        (1 << Registers::t1) |
-        (1 << Registers::t2) |
-        (1 << Registers::t3) |
-        (1 << Registers::t4) |
-        (1 << Registers::t5) |
-        (1 << Registers::t6) |
-        (1 << Registers::t7);
-
-    // We use this constant to save registers when entering functions. This
-    // is why $ra is added here even though it is not "Non Volatile".
-    static const SetType NonVolatileMask =
-        (1 << Registers::s0) |
-        (1 << Registers::s1) |
-        (1 << Registers::s2) |
-        (1 << Registers::s3) |
-        (1 << Registers::s4) |
-        (1 << Registers::s5) |
-        (1 << Registers::s6) |
-        (1 << Registers::s7) |
-        (1 << Registers::ra);
-
-    static const SetType WrapperMask =
-        VolatileMask |         // = arguments
-        (1 << Registers::t0) | // = outReg
-        (1 << Registers::t1);  // = argBase
-
-    static const SetType NonAllocatableMask =
-        (1 << Registers::zero) |
-        (1 << Registers::at) | // at = scratch
-        (1 << Registers::t8) | // t8 = scratch
-        (1 << Registers::t9) | // t9 = scratch
-        (1 << Registers::k0) |
-        (1 << Registers::k1) |
-        (1 << Registers::gp) |
-        (1 << Registers::sp) |
-        (1 << Registers::fp) |
-        (1 << Registers::ra);
-
-    // Registers that can be allocated without being saved, generally.
-    static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
-
-    // Registers returned from a JS -> JS call.
-    static const SetType JSCallMask =
-        (1 << Registers::a2) |
-        (1 << Registers::a3);
-
-    // Registers returned from a JS -> C call.
-    static const SetType CallMask =
-        (1 << Registers::v0) |
-        (1 << Registers::v1);  // used for double-size returns
-
-    static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
-
-    static uint32_t SetSize(SetType x) {
-        static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
-        return mozilla::CountPopulation32(x);
-    }
-    static uint32_t FirstBit(SetType x) {
-        return mozilla::CountTrailingZeroes32(x);
-    }
-    static uint32_t LastBit(SetType x) {
-        return 31 - mozilla::CountLeadingZeroes32(x);
-    }
-};
-
-// Smallest integer type that can hold a register bitmask.
-typedef uint32_t PackedRegisterMask;
-
-
 // MIPS32 can have two types of floating-point coprocessors:
 // - 32 bit floating-point coprocessor - In this case, there are 32 single
 // precision registers and pairs of even and odd float registers are used as
 // double precision registers. Example: f0 (double) is composed of
 // f0 and f1 (single).
 // - 64 bit floating-point coprocessor - In this case, there are 32 double
 // precision register which can also be used as single precision registers.
 
 // When using O32 ABI, floating-point coprocessor is 32 bit.
 // When using N32 ABI, floating-point coprocessor is 64 bit.
-class FloatRegisters
+class FloatRegisters : public BaseFloatRegisters
 {
   public:
-    enum FPRegisterID {
-        f0 = 0,
-        f1,
-        f2,
-        f3,
-        f4,
-        f5,
-        f6,
-        f7,
-        f8,
-        f9,
-        f10,
-        f11,
-        f12,
-        f13,
-        f14,
-        f15,
-        f16,
-        f17,
-        f18,
-        f19,
-        f20,
-        f21,
-        f22,
-        f23,
-        f24,
-        f25,
-        f26,
-        f27,
-        f28,
-        f29,
-        f30,
-        f31,
-        invalid_freg
-    };
-    typedef FPRegisterID Code;
-    typedef FPRegisterID Encoding;
-
-    // Content spilled during bailouts.
-    union RegisterContent {
-        double d;
-    };
-
-    static const char* GetName(Code code) {
-        static const char * const Names[] = { "f0", "f1", "f2", "f3",  "f4", "f5",  "f6", "f7",
-                                              "f8", "f9",  "f10", "f11", "f12", "f13",
-                                              "f14", "f15", "f16", "f17", "f18", "f19",
-                                              "f20", "f21", "f22", "f23", "f24", "f25",
-                                              "f26", "f27", "f28", "f29", "f30", "f31"};
-        return Names[code];
-    }
     static const char* GetName(uint32_t i) {
         MOZ_ASSERT(i < Total);
         return GetName(Code(i % 32));
     }
 
     static Code FromName(const char* name);
 
-    static const Code Invalid = invalid_freg;
-
     static const uint32_t Total = 64;
     static const uint32_t TotalDouble = 16;
     static const uint32_t TotalSingle = 32;
     static const uint32_t Allocatable = 42;
     // When saving all registers we only need to do is save double registers.
     static const uint32_t TotalPhys = 16;
 
-    typedef uint64_t SetType;
+    static_assert(sizeof(SetType) * 8 >= Total,
+                  "SetType should be large enough to enumerate all registers.");
+
     static const SetType AllDoubleMask = 0x55555555ULL << 32;
     static const SetType AllMask = AllDoubleMask | ((1ULL << 32) - 1);
 
     static const SetType NonVolatileDoubleMask =
         ((1ULL << FloatRegisters::f20) |
          (1ULL << FloatRegisters::f22) |
          (1ULL << FloatRegisters::f24) |
          (1ULL << FloatRegisters::f26) |
@@ -346,20 +123,17 @@ class FloatRegisters
         (1ULL << FloatRegisters::f19);
 
     // Registers that can be allocated without being saved, generally.
     static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
 
     static const SetType AllocatableMask = AllMask & ~NonAllocatableMask;
 };
 
-template <typename T>
-class TypedRegisterSet;
-
-class FloatRegister
+class FloatRegister : public BaseFloatRegister
 {
   public:
     enum RegType {
         Single = 0x0,
         Double = 0x1,
     };
 
     typedef FloatRegisters Codes;
@@ -386,18 +160,16 @@ class FloatRegister
     bool equiv(const FloatRegister& other) const { return other.kind_ == kind_; }
     size_t size() const { return (kind_ == Double) ? 8 : 4; }
     bool isInvalid() const {
         return code_ == FloatRegisters::invalid_freg;
     }
 
     bool isSingle() const { return kind_ == Single; }
     bool isDouble() const { return kind_ == Double; }
-    bool isInt32x4() const { return false; }
-    bool isFloat32x4() const { return false; }
 
     FloatRegister doubleOverlay(unsigned int which = 0) const;
     FloatRegister singleOverlay(unsigned int which = 0) const;
     FloatRegister sintOverlay(unsigned int which = 0) const;
     FloatRegister uintOverlay(unsigned int which = 0) const;
 
     FloatRegister asSingle() const { return singleOverlay(); }
     FloatRegister asDouble() const { return doubleOverlay(); }
@@ -484,69 +256,35 @@ class FloatRegister
         MOZ_ASSERT((code_ & 1) == 0);
         if (aliasIdx == 0) {
             *ret = *this;
             return;
         }
         MOZ_ASSERT(aliasIdx == 1);
         *ret = singleOverlay(aliasIdx - 1);
     }
-    typedef FloatRegisters::SetType SetType;
 
     SetType alignedOrDominatedAliasedSet() const {
         if (isSingle())
             return SetType(1) << code_;
 
         MOZ_ASSERT(isDouble());
         return SetType(0b11) << code_;
     }
 
-    static uint32_t SetSize(SetType x) {
-        static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
-        return mozilla::CountPopulation32(x);
-    }
     static Code FromName(const char* name) {
         return FloatRegisters::FromName(name);
     }
     static TypedRegisterSet<FloatRegister> ReduceSetForPush(const TypedRegisterSet<FloatRegister>& s);
     static uint32_t GetPushSizeInBytes(const TypedRegisterSet<FloatRegister>& s);
     uint32_t getRegisterDumpOffsetInBytes();
-    static uint32_t FirstBit(SetType x) {
-        return mozilla::CountTrailingZeroes64(x);
-    }
-    static uint32_t LastBit(SetType x) {
-        return 63 - mozilla::CountLeadingZeroes64(x);
-    }
 };
 
-uint32_t GetMIPSFlags();
-bool hasFPU();
-
-// MIPS doesn't have double registers that can NOT be treated as float32.
-inline bool
-hasUnaliasedDouble() {
-    return false;
-}
-
-// On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need
-// to convert a float32 to a double as a temporary, you need a temporary
-// double register.
-inline bool
-hasMultiAlias() {
-    return true;
-}
-
 // In order to handle functions such as int(*)(int, double) where the first
 // argument is a general purpose register, and the second argument is a floating
 // point register, we have to store the double content into 2 general purpose
 // registers, namely a2 and a3.
 #define JS_CODEGEN_REGISTER_PAIR 1
 
-// See the comments above AsmJSMappedSize in AsmJSValidate.h for more info.
-// TODO: Implement this for MIPS. Note that it requires Codegen to respect the
-// offset field of AsmJSHeapAccess.
-static const size_t AsmJSCheckedImmediateRange = 0;
-static const size_t AsmJSImmediateRange = 0;
-
 } // namespace jit
 } // namespace js
 
 #endif /* jit_mips32_Architecture_mips32_h */
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -457,31 +457,35 @@ elif CONFIG['JS_CODEGEN_ARM64']:
     if CONFIG['JS_SIMULATOR_ARM64']:
         UNIFIED_SOURCES += [
             'jit/arm64/vixl/Debugger-vixl.cpp',
             'jit/arm64/vixl/MozSimulator-vixl.cpp',
             'jit/arm64/vixl/Simulator-vixl.cpp'
         ]
 elif CONFIG['JS_CODEGEN_MIPS32']:
     UNIFIED_SOURCES += [
-        'jit/mips32/Architecture-mips32.cpp',
-        'jit/mips32/Assembler-mips32.cpp',
-        'jit/mips32/Bailouts-mips32.cpp',
-        'jit/mips32/BaselineCompiler-mips32.cpp',
-        'jit/mips32/BaselineIC-mips32.cpp',
-        'jit/mips32/CodeGenerator-mips32.cpp',
-        'jit/mips32/Lowering-mips32.cpp',
-        'jit/mips32/MacroAssembler-mips32.cpp',
-        'jit/mips32/MoveEmitter-mips32.cpp',
-        'jit/mips32/Trampoline-mips32.cpp',
+        'jit/mips-shared/Architecture-mips.cpp',
     ]
-    if CONFIG['JS_SIMULATOR_MIPS32']:
+    if CONFIG['JS_CODEGEN_MIPS32']:
         UNIFIED_SOURCES += [
-            'jit/mips32/Simulator-mips32.cpp'
+            'jit/mips32/Architecture-mips32.cpp',
+            'jit/mips32/Assembler-mips32.cpp',
+            'jit/mips32/Bailouts-mips32.cpp',
+            'jit/mips32/BaselineCompiler-mips32.cpp',
+            'jit/mips32/BaselineIC-mips32.cpp',
+            'jit/mips32/CodeGenerator-mips32.cpp',
+            'jit/mips32/Lowering-mips32.cpp',
+            'jit/mips32/MacroAssembler-mips32.cpp',
+            'jit/mips32/MoveEmitter-mips32.cpp',
+            'jit/mips32/Trampoline-mips32.cpp',
         ]
+        if CONFIG['JS_SIMULATOR_MIPS32']:
+            UNIFIED_SOURCES += [
+                'jit/mips32/Simulator-mips32.cpp'
+            ]
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     SOURCES += [
         'jit/ExecutableAllocatorWin.cpp',
     ]
     # _CRT_RAND_S must be #defined before #including stdlib.h to get rand_s()
     DEFINES['_CRT_RAND_S'] = True
 else: