Merge.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 13 Jan 2012 17:40:14 -0800
changeset 85663 21d52deaef00ae570639be613e9cc34fe7002840
parent 85662 2b2ca37b0305d1f41c42e26bd66b59bf0239e1b6 (current diff)
parent 85661 4dd329d75054a9d949f5b26197425ea3520888f3 (diff)
child 85664 40993c4c18d0dbec72587051a314a41abae69ab6
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone12.0a1
Merge.
--- a/build/unix/gnu-ld-scripts/components-mapfile
+++ b/build/unix/gnu-ld-scripts/components-mapfile
@@ -1,6 +1,7 @@
 {
    global:
 		NSModule;
 		NSGetModule;
+		__RLD_MAP;
    local: *;
 };
--- a/build/unix/gnu-ld-scripts/components-version-script
+++ b/build/unix/gnu-ld-scripts/components-version-script
@@ -1,6 +1,7 @@
 EXPORTED {
    global:
 		NSModule;
 		NSGetModule;
+		__RLD_MAP;
    local: *;
 };
--- a/ipc/chromium/Makefile.in
+++ b/ipc/chromium/Makefile.in
@@ -314,20 +314,22 @@ CSRCS += \
 endif # }
 
 endif # }
 
 endif # }
 
 ifneq (86,$(findstring 86,$(OS_TEST))) # {
 ifneq (arm,$(findstring arm,$(OS_TEST))) # {
+ifneq (mips,$(findstring mips,$(OS_TEST))) # {
 # Use mutex-backed atomics
 CPPSRCS += atomicops_internals_mutex.cc
 endif # }
 endif # }
+endif # }
 
 OS_CXXFLAGS += $(TK_CFLAGS)
 
 include $(topsrcdir)/config/rules.mk
 
 ifdef MOZ_NATIVE_LIBEVENT # {
 export::
 	mkdir -p $(DIST)/third_party/libevent
--- a/ipc/chromium/src/base/atomicops.h
+++ b/ipc/chromium/src/base/atomicops.h
@@ -131,13 +131,15 @@ Atomic64 Release_Load(volatile const Ato
 #if defined(OS_WIN) && defined(ARCH_CPU_X86_FAMILY)
 #include "base/atomicops_internals_x86_msvc.h"
 #elif defined(OS_MACOSX) && defined(ARCH_CPU_X86_FAMILY)
 #include "base/atomicops_internals_x86_macosx.h"
 #elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY)
 #include "base/atomicops_internals_x86_gcc.h"
 #elif defined(COMPILER_GCC) && defined(ARCH_CPU_ARM_FAMILY)
 #include "base/atomicops_internals_arm_gcc.h"
+#elif defined(COMPILER_GCC) && defined(ARCH_CPU_MIPS)
+#include "base/atomicops_internals_mips_gcc.h"
 #else
 #include "base/atomicops_internals_mutex.h"
 #endif
 
 #endif  // BASE_ATOMICOPS_H_
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -328,16 +328,19 @@ endif
 endif
 endif
 ifeq (arm, $(TARGET_CPU))
 #CPPSRCS		+= only_on_arm.cpp
 endif
 ifeq (sparc, $(findstring sparc,$(TARGET_CPU)))
 ASFILES +=	TrampolineSparc.s
 endif
+ifeq (mips, $(findstring mips,$(TARGET_CPU)))
+CPPSRCS +=	TrampolineMIPS.cpp
+endif
 #
 # END enclude sources for the method JIT
 #############################################
 
 endif
 
 ###############################################
 # BEGIN include sources for V8 dtoa
@@ -356,17 +359,17 @@ CPPSRCS += 	checks.cc \
 
 #
 # END enclude sources for V8 dtoa
 #############################################
 
 # For architectures without YARR JIT, PCRE is faster than the YARR
 # interpreter (bug 684559).
 
-ifeq (,$(filter arm% sparc %86 x86_64,$(TARGET_CPU)))
+ifeq (,$(filter arm% sparc %86 x86_64 mips%,$(TARGET_CPU)))
 
 VPATH +=        $(srcdir)/yarr/pcre \
 		$(NULL)
 
 CPPSRCS += \
                 pcre_compile.cpp \
                 pcre_exec.cpp \
                 pcre_tables.cpp \
new file mode 100644
--- /dev/null
+++ b/js/src/assembler/assembler/MIPSAssembler.h
@@ -0,0 +1,1089 @@
+/*
+ * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 University of Szeged
+ * All rights reserved.
+ * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MIPSAssembler_h
+#define MIPSAssembler_h
+
+#if ENABLE(ASSEMBLER) && CPU(MIPS)
+
+#include "AssemblerBuffer.h"
+#include "assembler/wtf/Assertions.h"
+#include "assembler/wtf/SegmentedVector.h"
+
+#include "methodjit/Logging.h"
+#define IPFX  "        %s"
+#define ISPFX "        "
+#ifdef JS_METHODJIT_SPEW
+# define MAYBE_PAD (isOOLPath ? ">  " : "")
+# define PRETTY_PRINT_OFFSET(os) (((os)<0)?"-":""), (((os)<0)?-(os):(os))
+# define FIXME_INSN_PRINTING                                \
+    do {                                                    \
+        js::JaegerSpew(js::JSpew_Insns,                     \
+                       ISPFX "FIXME insn printing %s:%d\n", \
+                       __FILE__, __LINE__);                 \
+    } while (0)
+#else
+# define MAYBE_PAD ""
+# define FIXME_INSN_PRINTING ((void) 0)
+# define PRETTY_PRINT_OFFSET(os) "", 0
+#endif
+
+namespace JSC {
+
+typedef uint32_t MIPSWord;
+
+namespace MIPSRegisters {
+typedef enum {
+    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
+} RegisterID;
+
+typedef enum {
+    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
+} FPRegisterID;
+
+} // namespace MIPSRegisters
+
+class MIPSAssembler {
+public:
+    typedef MIPSRegisters::RegisterID RegisterID;
+    typedef MIPSRegisters::FPRegisterID FPRegisterID;
+    typedef SegmentedVector<int, 64> Jumps;
+    unsigned char *buffer() const { return m_buffer.buffer(); }
+    bool oom() const { return m_buffer.oom(); }
+
+#ifdef JS_METHODJIT_SPEW
+    bool isOOLPath;
+    MIPSAssembler() : isOOLPath(false) { }
+#else
+    MIPSAssembler() { }
+#endif
+
+    // MIPS instruction opcode field position
+    enum {
+        OP_SH_RD = 11,
+        OP_SH_RT = 16,
+        OP_SH_RS = 21,
+        OP_SH_SHAMT = 6,
+        OP_SH_CODE = 16,
+        OP_SH_FD = 6,
+        OP_SH_FS = 11,
+        OP_SH_FT = 16
+    };
+
+    class JmpSrc {
+        friend class MIPSAssembler;
+    public:
+        JmpSrc()
+            : m_offset(-1)
+        {
+        }
+
+    private:
+        JmpSrc(int offset)
+            : m_offset(offset)
+        {
+        }
+
+        int m_offset;
+    };
+
+    class JmpDst {
+        friend class MIPSAssembler;
+    public:
+        JmpDst()
+            : m_offset(-1)
+            , m_used(false)
+        {
+        }
+
+        bool isUsed() const { return m_used; }
+        void used() { m_used = true; }
+        bool isValid() const { return m_offset != -1; }
+    private:
+        JmpDst(int offset)
+            : m_offset(offset)
+            , m_used(false)
+        {
+            ASSERT(m_offset == offset);
+        }
+
+        int m_offset : 31;
+        int m_used : 1;
+    };
+
+    void emitInst(MIPSWord op)
+    {
+        void* oldBase = m_buffer.data();
+
+        m_buffer.putInt(op);
+
+        void* newBase = m_buffer.data();
+        if (oldBase != newBase)
+            relocateJumps(oldBase, newBase);
+    }
+
+    void nop()
+    {
+        emitInst(0x00000000);
+    }
+
+    /* Need to insert one load data delay nop for mips1.  */
+    void loadDelayNop()
+    {
+#if WTF_MIPS_ISA(1)
+        nop();
+#endif
+    }
+
+    /* Need to insert one coprocessor access delay nop for mips1.  */
+    void copDelayNop()
+    {
+#if WTF_MIPS_ISA(1)
+        nop();
+#endif
+    }
+
+    void movz(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x0000000a | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void move(RegisterID rd, RegisterID rs)
+    {
+        /* addu */
+        emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS));
+    }
+
+    /* Set an immediate value to a register.  This may generate 1 or 2
+       instructions.  */
+    void li(RegisterID dest, int imm)
+    {
+        if (imm >= -32768 && imm <= 32767)
+            addiu(dest, MIPSRegisters::zero, imm);
+        else if (imm >= 0 && imm < 65536)
+            ori(dest, MIPSRegisters::zero, imm);
+        else {
+            lui(dest, imm >> 16);
+            if (imm & 0xffff)
+                ori(dest, dest, imm);
+        }
+    }
+
+    void lui(RegisterID rt, int imm)
+    {
+        emitInst(0x3c000000 | (rt << OP_SH_RT) | (imm & 0xffff));
+    }
+
+    void addiu(RegisterID rt, RegisterID rs, int imm)
+    {
+        emitInst(0x24000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (imm & 0xffff));
+    }
+
+    void addu(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000021 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void subu(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000023 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void mult(RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000018 | (rs << OP_SH_RS) | (rt << OP_SH_RT));
+    }
+
+    void div(RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x0000001a | (rs << OP_SH_RS) | (rt << OP_SH_RT));
+    }
+
+    void mfhi(RegisterID rd)
+    {
+        emitInst(0x00000010 | (rd << OP_SH_RD));
+    }
+
+    void mflo(RegisterID rd)
+    {
+        emitInst(0x00000012 | (rd << OP_SH_RD));
+    }
+
+    void mul(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+#if WTF_MIPS_ISA_AT_LEAST(32) 
+        emitInst(0x70000002 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+#else
+        mult(rs, rt);
+        mflo(rd);
+#endif
+    }
+
+    void andInsn(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000024 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void andi(RegisterID rt, RegisterID rs, int imm)
+    {
+        emitInst(0x30000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (imm & 0xffff));
+    }
+
+    void nor(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000027 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void orInsn(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000025 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void ori(RegisterID rt, RegisterID rs, int imm)
+    {
+        emitInst(0x34000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (imm & 0xffff));
+    }
+
+    void xorInsn(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x00000026 | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void xori(RegisterID rt, RegisterID rs, int imm)
+    {
+        emitInst(0x38000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (imm & 0xffff));
+    }
+
+    void slt(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x0000002a | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void sltu(RegisterID rd, RegisterID rs, RegisterID rt)
+    {
+        emitInst(0x0000002b | (rd << OP_SH_RD) | (rs << OP_SH_RS)
+                 | (rt << OP_SH_RT));
+    }
+
+    void sltiu(RegisterID rt, RegisterID rs, int imm)
+    {
+        emitInst(0x2c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (imm & 0xffff));
+    }
+
+    void sll(RegisterID rd, RegisterID rt, int shamt)
+    {
+        emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | ((shamt & 0x1f) << OP_SH_SHAMT));
+    }
+
+    void sllv(RegisterID rd, RegisterID rt, int rs)
+    {
+        emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | (rs << OP_SH_RS));
+    }
+
+    void sra(RegisterID rd, RegisterID rt, int shamt)
+    {
+        emitInst(0x00000003 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | ((shamt & 0x1f) << OP_SH_SHAMT));
+    }
+
+    void srav(RegisterID rd, RegisterID rt, RegisterID rs)
+    {
+        emitInst(0x00000007 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | (rs << OP_SH_RS));
+    }
+
+    void srl(RegisterID rd, RegisterID rt, int shamt)
+    {
+        emitInst(0x00000002 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | ((shamt & 0x1f) << OP_SH_SHAMT));
+    }
+
+    void srlv(RegisterID rd, RegisterID rt, RegisterID rs)
+    {
+        emitInst(0x00000006 | (rd << OP_SH_RD) | (rt << OP_SH_RT)
+                 | (rs << OP_SH_RS));
+    }
+
+    void lb(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x80000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lbu(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x90000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lw(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x8c000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lwl(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x88000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lwr(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x98000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lh(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x84000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void lhu(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0x94000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        loadDelayNop();
+    }
+
+    void sb(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0xa0000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void sh(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0xa4000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void sw(RegisterID rt, RegisterID rs, int offset)
+    {
+        emitInst(0xac000000 | (rt << OP_SH_RT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void jr(RegisterID rs)
+    {
+        emitInst(0x00000008 | (rs << OP_SH_RS));
+    }
+
+    void jalr(RegisterID rs)
+    {
+        emitInst(0x0000f809 | (rs << OP_SH_RS));
+    }
+
+    void jal()
+    {
+        emitInst(0x0c000000);
+    }
+
+    void bkpt()
+    {
+        int value = 512; /* BRK_BUG */
+        emitInst(0x0000000d | ((value & 0x3ff) << OP_SH_CODE));
+    }
+
+    void bgez(RegisterID rs, int imm)
+    {
+        emitInst(0x04010000 | (rs << OP_SH_RS) | (imm & 0xffff));
+    }
+
+    void bltz(RegisterID rs, int imm)
+    {
+        emitInst(0x04000000 | (rs << OP_SH_RS) | (imm & 0xffff));
+    }
+
+    void beq(RegisterID rs, RegisterID rt, int imm)
+    {
+        emitInst(0x10000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
+    }
+
+    void bne(RegisterID rs, RegisterID rt, int imm)
+    {
+        emitInst(0x14000000 | (rs << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff));
+    }
+
+    void bc1t()
+    {
+        emitInst(0x45010000);
+    }
+
+    void bc1f()
+    {
+        emitInst(0x45000000);
+    }
+
+    JmpSrc newJmpSrc()
+    {
+        return JmpSrc(m_buffer.size());
+    }
+
+    void appendJump()
+    {
+        m_jumps.append(m_buffer.size());
+    }
+
+    void movd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void addd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200000 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
+                 | (ft << OP_SH_FT));
+    }
+
+    void subd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200001 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
+                 | (ft << OP_SH_FT));
+    }
+
+    void muld(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200002 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
+                 | (ft << OP_SH_FT));
+    }
+
+    void divd(FPRegisterID fd, FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200003 | (fd << OP_SH_FD) | (fs << OP_SH_FS)
+                 | (ft << OP_SH_FT));
+    }
+
+    void negd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200007 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void absd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200005 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void lwc1(FPRegisterID ft, RegisterID rs, int offset)
+    {
+        emitInst(0xc4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+        copDelayNop();
+    }
+
+    void ldc1(FPRegisterID ft, RegisterID rs, int offset)
+    {
+        emitInst(0xd4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void swc1(FPRegisterID ft, RegisterID rs, int offset)
+    {
+        emitInst(0xe4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void sdc1(FPRegisterID ft, RegisterID rs, int offset)
+    {
+        emitInst(0xf4000000 | (ft << OP_SH_FT) | (rs << OP_SH_RS)
+                 | (offset & 0xffff));
+    }
+
+    void mtc1(RegisterID rt, FPRegisterID fs)
+    {
+        emitInst(0x44800000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
+        copDelayNop();
+    }
+
+    void mthc1(RegisterID rt, FPRegisterID fs)
+    {
+        emitInst(0x44e00000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
+        copDelayNop();
+    }
+
+    void mfc1(RegisterID rt, FPRegisterID fs)
+    {
+        emitInst(0x44000000 | (fs << OP_SH_FS) | (rt << OP_SH_RT));
+        copDelayNop();
+    }
+
+    void sqrtd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void truncwd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void cvtdw(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46800021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void cvtds(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46000021 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void cvtsd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200020 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void cvtwd(FPRegisterID fd, FPRegisterID fs)
+    {
+        emitInst(0x46200024 | (fd << OP_SH_FD) | (fs << OP_SH_FS));
+    }
+
+    void ceqd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200032 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cngtd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x4620003f | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cnged(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x4620003d | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cltd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x4620003c | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cled(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x4620003e | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cueqd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200033 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void coled(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200036 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void coltd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200034 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void culed(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200037 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    void cultd(FPRegisterID fs, FPRegisterID ft)
+    {
+        emitInst(0x46200035 | (fs << OP_SH_FS) | (ft << OP_SH_FT));
+        copDelayNop();
+    }
+
+    // General helpers
+
+    JmpDst label()
+    {
+        return JmpDst(m_buffer.size());
+    }
+
+    JmpDst align(int alignment)
+    {
+        while (!m_buffer.isAligned(alignment))
+            bkpt();
+
+        return label();
+    }
+
+    static void* getRelocatedAddress(void* code, JmpSrc jump)
+    {
+        ASSERT(jump.m_offset != -1);
+        void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + jump.m_offset);
+        return b;
+    }
+
+    static void* getRelocatedAddress(void* code, JmpDst label)
+    {
+        void* b = reinterpret_cast<void*>((reinterpret_cast<intptr_t>(code)) + label.m_offset);
+        return b;
+    }
+
+    static int getDifferenceBetweenLabels(JmpDst from, JmpDst to)
+    {
+        return to.m_offset - from.m_offset;
+    }
+
+    static int getDifferenceBetweenLabels(JmpDst from, JmpSrc to)
+    {
+        return to.m_offset - from.m_offset;
+    }
+
+    static int getDifferenceBetweenLabels(JmpSrc from, JmpDst to)
+    {
+        return to.m_offset - from.m_offset;
+    }
+
+    // Assembler admin methods:
+
+    size_t size() const
+    {
+        return m_buffer.size();
+    }
+
+    void executableCopy(void* buffer)
+    {
+        memcpy(buffer, m_buffer.data(), m_buffer.size());
+        relocateJumps(m_buffer.data(), buffer);
+    }
+
+    void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool** poolp, CodeKind kind)
+    {
+        void *result = m_buffer.executableAllocAndCopy(allocator, poolp, kind);
+        if (!result)
+          return 0;
+
+        relocateJumps(m_buffer.data(), result);
+        return result;
+    }
+
+    static unsigned getCallReturnOffset(JmpSrc call)
+    {
+        // The return address is after a call and a delay slot instruction
+        return call.m_offset;
+    }
+
+    // Linking & patching:
+    //
+    // 'link' and 'patch' methods are for use on unprotected code - such as the code
+    // within the AssemblerBuffer, and code being patched by the patch buffer.  Once
+    // code has been finalized it is (platform support permitting) within a non-
+    // writable region of memory; to modify the code in an execute-only execuable
+    // pool the 'repatch' and 'relink' methods should be used.
+
+    void linkJump(JmpSrc from, JmpDst to)
+    {
+        ASSERT(to.m_offset != -1);
+        ASSERT(from.m_offset != -1);
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + from.m_offset);
+        MIPSWord* toPos = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(m_buffer.data()) + to.m_offset);
+
+        ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
+        insn = insn - 6;
+        linkWithOffset(insn, toPos);
+    }
+
+    static void linkJump(void* code, JmpSrc from, void* to)
+    {
+        ASSERT(from.m_offset != -1);
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
+
+        ASSERT(!(*(insn - 1)) && !(*(insn - 2)) && !(*(insn - 3)) && !(*(insn - 5)));
+        insn = insn - 6;
+        linkWithOffset(insn, to);
+    }
+
+    static bool canRelinkJump(void* from, void* to)
+    {
+        return true;
+    }
+
+    static void linkCall(void* code, JmpSrc from, void* to)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
+        linkCallInternal(insn, to);
+    }
+
+    static void linkPointer(void* code, JmpDst from, void* to)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(code) + from.m_offset);
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
+        insn++;
+        ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
+        *insn = (*insn & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
+    }
+
+    static void relinkJump(void* from, void* to)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+
+        ASSERT(!(*(insn - 1)) && !(*(insn - 5)));
+        insn = insn - 6;
+        int flushSize = linkWithOffset(insn, to);
+
+        ExecutableAllocator::cacheFlush(insn, flushSize);
+    }
+
+    static void relinkCall(void* from, void* to)
+    {
+        void* start;
+        int size = linkCallInternal(from, to);
+        if (size == sizeof(MIPSWord))
+            start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 2 * sizeof(MIPSWord));
+        else
+            start = reinterpret_cast<void*>(reinterpret_cast<intptr_t>(from) - 4 * sizeof(MIPSWord));
+
+        ExecutableAllocator::cacheFlush(start, size);
+    }
+
+    static void repatchInt32(void* from, int32_t to)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        *insn = (*insn & 0xffff0000) | ((to >> 16) & 0xffff);
+        insn++;
+        ASSERT((*insn & 0xfc000000) == 0x34000000); // ori
+        *insn = (*insn & 0xffff0000) | (to & 0xffff);
+        insn--;
+        ExecutableAllocator::cacheFlush(insn, 2 * sizeof(MIPSWord));
+    }
+
+    static void repatchPointer(void* from, void* to)
+    {
+        repatchInt32(from, reinterpret_cast<int32_t>(to));
+    }
+
+    static void repatchLoadPtrToLEA(void* from)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        insn = insn + 3;
+        ASSERT((*insn & 0xfc000000) == 0x8c000000); // lw
+        /* lw -> addiu */
+        *insn = 0x24000000 | (*insn & 0x03ffffff);
+
+        ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
+    }
+
+    static void repatchLEAToLoadPtr(void* from)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        insn = insn + 3;
+        if ((*insn & 0xfc000000) == 0x8c000000)
+          return; // Valid lw instruction
+
+        ASSERT((*insn & 0xfc000000) == 0x24000000); // addiu
+        /* addiu -> lw */
+        *insn = 0x8c000000 | (*insn & 0x03ffffff);
+
+        ExecutableAllocator::cacheFlush(insn, sizeof(MIPSWord));
+    }
+
+private:
+
+    /* Update each jump in the buffer of newBase.  */
+    void relocateJumps(void* oldBase, void* newBase)
+    {
+        // Check each jump
+        for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) {
+            int pos = *iter;
+            MIPSWord* insn = reinterpret_cast<MIPSWord*>(reinterpret_cast<intptr_t>(newBase) + pos);
+            insn = insn + 2;
+            // Need to make sure we have 5 valid instructions after pos
+            if ((unsigned int)pos >= m_buffer.size() - 5 * sizeof(MIPSWord))
+                continue;
+
+            if ((*insn & 0xfc000000) == 0x08000000) { // j
+                int offset = *insn & 0x03ffffff;
+                int oldInsnAddress = (int)insn - (int)newBase + (int)oldBase;
+                int topFourBits = (oldInsnAddress + 4) >> 28;
+                int oldTargetAddress = (topFourBits << 28) | (offset << 2);
+                int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
+                int newInsnAddress = (int)insn;
+                if (((newInsnAddress + 4) >> 28) == (newTargetAddress >> 28))
+                    *insn = 0x08000000 | ((newTargetAddress >> 2) & 0x3ffffff);
+                else {
+                    /* lui */
+                    *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
+                    /* ori */
+                    *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
+                    /* jr */
+                    *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
+                }
+            } else if ((*insn & 0xffe00000) == 0x3c000000) { // lui
+                int high = (*insn & 0xffff) << 16;
+                int low = *(insn + 1) & 0xffff;
+                int oldTargetAddress = high | low;
+                int newTargetAddress = oldTargetAddress - (int)oldBase + (int)newBase;
+                /* lui */
+                *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
+                /* ori */
+                *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
+            }
+        }
+    }
+
+    static int linkWithOffset(MIPSWord* insn, void* to)
+    {
+        ASSERT((*insn & 0xfc000000) == 0x10000000 // beq
+               || (*insn & 0xfc000000) == 0x14000000 // bne
+               || (*insn & 0xffff0000) == 0x45010000 // bc1t
+               || (*insn & 0xffff0000) == 0x45000000); // bc1f
+        intptr_t diff = (reinterpret_cast<intptr_t>(to)
+                         - reinterpret_cast<intptr_t>(insn) - 4) >> 2;
+
+        if (diff < -32768 || diff > 32767 || *(insn + 2) != 0x10000003) {
+            /*
+                Convert the sequence:
+                  beq $2, $3, target
+                  nop
+                  b 1f
+                  nop
+                  nop
+                  nop
+                1:
+
+                to the new sequence if possible:
+                  bne $2, $3, 1f
+                  nop
+                  j    target
+                  nop
+                  nop
+                  nop
+                1:
+
+                OR to the new sequence:
+                  bne $2, $3, 1f
+                  nop
+                  lui $25, target >> 16
+                  ori $25, $25, target & 0xffff
+                  jr $25
+                  nop
+                1:
+
+                Note: beq/bne/bc1t/bc1f are converted to bne/beq/bc1f/bc1t.
+            */
+
+            if (*(insn + 2) == 0x10000003) {
+                if ((*insn & 0xfc000000) == 0x10000000) // beq
+                    *insn = (*insn & 0x03ff0000) | 0x14000005; // bne
+                else if ((*insn & 0xfc000000) == 0x14000000) // bne
+                    *insn = (*insn & 0x03ff0000) | 0x10000005; // beq
+                else if ((*insn & 0xffff0000) == 0x45010000) // bc1t
+                    *insn = 0x45000005; // bc1f
+                else if ((*insn & 0xffff0000) == 0x45000000) // bc1f
+                    *insn = 0x45010005; // bc1t
+                else
+                    ASSERT(0);
+            }
+
+            insn = insn + 2;
+            if ((reinterpret_cast<intptr_t>(insn) + 4) >> 28
+                == reinterpret_cast<intptr_t>(to) >> 28) {
+                *insn = 0x08000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
+                *(insn + 1) = 0;
+                return 4 * sizeof(MIPSWord);
+            }
+
+            intptr_t newTargetAddress = reinterpret_cast<intptr_t>(to);
+            /* lui */
+            *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((newTargetAddress >> 16) & 0xffff);
+            /* ori */
+            *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (newTargetAddress & 0xffff);
+            /* jr */
+            *(insn + 2) = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS);
+            return 5 * sizeof(MIPSWord);
+        }
+
+        *insn = (*insn & 0xffff0000) | (diff & 0xffff);
+        return sizeof(MIPSWord);
+    }
+
+    static int linkCallInternal(void* from, void* to)
+    {
+        MIPSWord* insn = reinterpret_cast<MIPSWord*>(from);
+        insn = insn - 4;
+
+        if ((*(insn + 2) & 0xfc000000) == 0x0c000000) { // jal
+            if ((reinterpret_cast<intptr_t>(from) - 4) >> 28
+                == reinterpret_cast<intptr_t>(to) >> 28) {
+                *(insn + 2) = 0x0c000000 | ((reinterpret_cast<intptr_t>(to) >> 2) & 0x3ffffff);
+                return sizeof(MIPSWord);
+            }
+
+            /* lui $25, (to >> 16) & 0xffff */
+            *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
+            /* ori $25, $25, to & 0xffff */
+            *(insn + 1) = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (reinterpret_cast<intptr_t>(to) & 0xffff);
+            /* jalr $25 */
+            *(insn + 2) = 0x0000f809 | (MIPSRegisters::t9 << OP_SH_RS);
+            return 3 * sizeof(MIPSWord);
+        }
+
+        ASSERT((*insn & 0xffe00000) == 0x3c000000); // lui
+        ASSERT((*(insn + 1) & 0xfc000000) == 0x34000000); // ori
+
+        /* lui */
+        *insn = (*insn & 0xffff0000) | ((reinterpret_cast<intptr_t>(to) >> 16) & 0xffff);
+        /* ori */
+        *(insn + 1) = (*(insn + 1) & 0xffff0000) | (reinterpret_cast<intptr_t>(to) & 0xffff);
+        return 2 * sizeof(MIPSWord);
+    }
+
+    AssemblerBuffer m_buffer;
+    Jumps m_jumps;
+};
+
+} // namespace JSC
+
+#endif // ENABLE(ASSEMBLER) && CPU(MIPS)
+
+#endif // MIPSAssembler_h
new file mode 100644
--- /dev/null
+++ b/js/src/assembler/assembler/MacroAssemblerMIPS.h
@@ -0,0 +1,2790 @@
+/*
+ * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 MIPS Technologies, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY MIPS TECHNOLOGIES, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL MIPS TECHNOLOGIES, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef MacroAssemblerMIPS_h
+#define MacroAssemblerMIPS_h
+
+#if ENABLE(ASSEMBLER) && CPU(MIPS)
+
+#include "AbstractMacroAssembler.h"
+#include "MIPSAssembler.h"
+
+namespace JSC {
+
+class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
+public:
+    typedef MIPSRegisters::FPRegisterID FPRegisterID;
+
+    MacroAssemblerMIPS()
+        : m_fixedWidth(false)
+    {
+    }
+
+    static const Scale ScalePtr = TimesFour;
+    static const unsigned int TotalRegisters = 24; // Count from $0 to $23
+						   // to leave the bitmask for
+						   // 8 FP registers.
+
+    // For storing immediate number
+    static const RegisterID immTempRegister = MIPSRegisters::t0;
+    // For storing data loaded from the memory
+    static const RegisterID dataTempRegister = MIPSRegisters::t1;
+    // For storing address base
+    static const RegisterID addrTempRegister = MIPSRegisters::t2;
+    // For storing compare result
+    static const RegisterID cmpTempRegister = MIPSRegisters::t3;
+    // For storing data loaded from the memory
+    static const RegisterID dataTemp2Register = MIPSRegisters::t4;
+
+    // FP temp register
+    static const FPRegisterID fpTempRegister = MIPSRegisters::f16;
+
+    enum Condition {
+        Equal,
+        NotEqual,
+        Above,
+        AboveOrEqual,
+        Below,
+        BelowOrEqual,
+        GreaterThan,
+        GreaterThanOrEqual,
+        LessThan,
+        LessThanOrEqual,
+        Overflow,
+        Signed,
+        Zero,
+        NonZero
+    };
+
+    enum DoubleCondition {
+        DoubleEqual,
+        DoubleNotEqual,
+        DoubleGreaterThan,
+        DoubleGreaterThanOrEqual,
+        DoubleLessThan,
+        DoubleLessThanOrEqual,
+        DoubleEqualOrUnordered,
+        DoubleNotEqualOrUnordered,
+        DoubleGreaterThanOrUnordered,
+        DoubleGreaterThanOrEqualOrUnordered,
+        DoubleLessThanOrUnordered,
+        DoubleLessThanOrEqualOrUnordered
+    };
+
+    static const RegisterID stackPointerRegister = MIPSRegisters::sp;
+    static const RegisterID returnAddressRegister = MIPSRegisters::ra;
+
+    // Integer arithmetic operations:
+    //
+    // Operations are typically two operand - operation(source, srcDst)
+    // For many operations the source may be an Imm32, the srcDst operand
+    // may often be a memory location (explictly described using an Address
+    // object).
+
+    void lea(Address address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.addiu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                addiu   dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.addiu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void lea(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                addiu   dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.addiu(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                addiu   dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.addiu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void add32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.addu(dest, dest, src);
+    }
+
+    void add32(TrustedImm32 imm, RegisterID dest)
+    {
+        add32(imm, dest, dest);
+    }
+
+    void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
+            && !m_fixedWidth) {
+            /*
+              addiu     dest, src, imm
+            */
+            m_assembler.addiu(dest, src, imm.m_value);
+        } else {
+            /*
+              li        immTemp, imm
+              addu      dest, src, immTemp
+            */
+            move(imm, immTempRegister);
+            m_assembler.addu(dest, src, immTempRegister);
+        }
+    }
+
+    void add32(TrustedImm32 imm, Address address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+              lw        dataTemp, offset(base)
+              li        immTemp, imm
+              addu      dataTemp, dataTemp, immTemp
+              sw        dataTemp, offset(base)
+            */
+            m_assembler.lw(dataTempRegister, address.base, address.offset);
+            if (!imm.m_isPointer
+                && imm.m_value >= -32768 && imm.m_value <= 32767
+                && !m_fixedWidth)
+                m_assembler.addiu(dataTempRegister, dataTempRegister,
+                                  imm.m_value);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.addu(dataTempRegister, dataTempRegister,
+                                 immTempRegister);
+            }
+            m_assembler.sw(dataTempRegister, address.base, address.offset);
+        } else {
+            /*
+              lui       addrTemp, (offset + 0x8000) >> 16
+              addu      addrTemp, addrTemp, base
+              lw        dataTemp, (offset & 0xffff)(addrTemp)
+              li        immtemp, imm
+              addu      dataTemp, dataTemp, immTemp
+              sw        dataTemp, (offset & 0xffff)(addrTemp)
+            */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
+
+            if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
+                m_assembler.addiu(dataTempRegister, dataTempRegister,
+                                  imm.m_value);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.addu(dataTempRegister, dataTempRegister,
+                                 immTempRegister);
+            }
+            m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
+        }
+    }
+
+    void add32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        add32(dataTempRegister, dest);
+    }
+
+    void add32(RegisterID src, Address dest)
+    {
+        if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
+            /*
+              lw        dataTemp, offset(base)
+              addu      dataTemp, dataTemp, src
+              sw        dataTemp, offset(base)
+            */
+            m_assembler.lw(dataTempRegister, dest.base, dest.offset);
+            m_assembler.addu(dataTempRegister, dataTempRegister, src);
+            m_assembler.sw(dataTempRegister, dest.base, dest.offset);
+        } else {
+            /*
+              lui       addrTemp, (offset + 0x8000) >> 16
+              addu      addrTemp, addrTemp, base
+              lw        dataTemp, (offset & 0xffff)(addrTemp)
+              addu      dataTemp, dataTemp, src
+              sw        dataTemp, (offset & 0xffff)(addrTemp)
+            */
+            m_assembler.lui(addrTempRegister, (dest.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, dest.base);
+            m_assembler.lw(dataTempRegister, addrTempRegister, dest.offset);
+            m_assembler.addu(dataTempRegister, dataTempRegister, src);
+            m_assembler.sw(dataTempRegister, addrTempRegister, dest.offset);
+        }
+    }
+
+    void add32(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        /*
+           li   addrTemp, address
+           li   immTemp, imm
+           lw   dataTemp, 0(addrTemp)
+           addu dataTemp, dataTemp, immTemp
+           sw   dataTemp, 0(addrTemp)
+        */
+        move(ImmPtr(address.m_ptr), addrTempRegister);
+        m_assembler.lw(dataTempRegister, addrTempRegister, 0);
+        if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
+            && !m_fixedWidth)
+            m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
+        else {
+            move(imm, immTempRegister);
+            m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
+        }
+        m_assembler.sw(dataTempRegister, addrTempRegister, 0);
+    }
+
+    // If src is (0x7FF7FFFF<<1), we will convert it to (0x7FF80000<<1).
+    void setShiftedCanonicalNaN(RegisterID src, RegisterID dest)
+    {
+        /*
+           li   dataTemp, (0x7FF80000<<1)
+           li   immTemp, (0x7FF7FFFF<<1)
+           xor  immTemp, immTemp, src
+           move dest, src
+           movz dest, dataTemp, immTemp
+        */
+        move(TrustedImm32(0x7FF80000 << 1), dataTempRegister);
+        move(TrustedImm32(0x7FF7FFFF << 1), immTempRegister);
+        xor32(src, immTempRegister);
+        move(src, dest);
+        m_assembler.movz(dest, dataTempRegister, immTempRegister);
+    }
+
+    void and32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        m_assembler.andInsn(dest, dest, dataTempRegister);
+    }
+
+    void and32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.andInsn(dest, dest, src);
+    }
+
+    void and32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+            move(MIPSRegisters::zero, dest);
+        else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
+                 && !m_fixedWidth)
+            m_assembler.andi(dest, dest, imm.m_value);
+        else {
+            /*
+              li        immTemp, imm
+              and       dest, dest, immTemp
+            */
+            move(imm, immTempRegister);
+            m_assembler.andInsn(dest, dest, immTempRegister);
+        }
+    }
+
+    void lshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.sll(dest, dest, imm.m_value);
+    }
+
+    void lshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.sllv(dest, dest, shiftAmount);
+    }
+
+    void mul32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.mul(dest, dest, src);
+    }
+
+    void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+            move(MIPSRegisters::zero, dest);
+        else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth)
+            move(src, dest);
+        else {
+            /*
+                li      dataTemp, imm
+                mul     dest, src, dataTemp
+            */
+            move(imm, dataTempRegister);
+            m_assembler.mul(dest, src, dataTempRegister);
+        }
+    }
+
+    void neg32(RegisterID srcDest)
+    {
+        m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
+    }
+
+    void not32(RegisterID srcDest)
+    {
+        m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
+    }
+
+    void or32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        m_assembler.orInsn(dest, dest, dataTempRegister);
+    }
+
+    void or32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.orInsn(dest, dest, src);
+    }
+
+    void or32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+            return;
+
+        if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
+            && !m_fixedWidth) {
+            m_assembler.ori(dest, dest, imm.m_value);
+            return;
+        }
+
+        /*
+            li      dataTemp, imm
+            or      dest, dest, dataTemp
+        */
+        move(imm, dataTempRegister);
+        m_assembler.orInsn(dest, dest, dataTempRegister);
+    }
+
+    void rshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.srav(dest, dest, shiftAmount);
+    }
+
+    void rshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.sra(dest, dest, imm.m_value);
+    }
+
+    void urshift32(RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.srlv(dest, dest, shiftAmount);
+    }
+
+    void urshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.srl(dest, dest, imm.m_value);
+    }
+
+    void sub32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.subu(dest, dest, src);
+    }
+
+    void sub32(TrustedImm32 imm, RegisterID dest)
+    {
+        if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
+            && !m_fixedWidth) {
+            /*
+              addiu     dest, src, imm
+            */
+            m_assembler.addiu(dest, dest, -imm.m_value);
+        } else {
+            /*
+              li        immTemp, imm
+              subu      dest, src, immTemp
+            */
+            move(imm, immTempRegister);
+            m_assembler.subu(dest, dest, immTempRegister);
+        }
+    }
+
+    void sub32(TrustedImm32 imm, Address address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+              lw        dataTemp, offset(base)
+              li        immTemp, imm
+              subu      dataTemp, dataTemp, immTemp
+              sw        dataTemp, offset(base)
+            */
+            m_assembler.lw(dataTempRegister, address.base, address.offset);
+            if (!imm.m_isPointer
+                && imm.m_value >= -32767 && imm.m_value <= 32768
+                && !m_fixedWidth)
+                m_assembler.addiu(dataTempRegister, dataTempRegister,
+                                  -imm.m_value);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.subu(dataTempRegister, dataTempRegister,
+                                 immTempRegister);
+            }
+            m_assembler.sw(dataTempRegister, address.base, address.offset);
+        } else {
+            /*
+              lui       addrTemp, (offset + 0x8000) >> 16
+              addu      addrTemp, addrTemp, base
+              lw        dataTemp, (offset & 0xffff)(addrTemp)
+              li        immtemp, imm
+              subu      dataTemp, dataTemp, immTemp
+              sw        dataTemp, (offset & 0xffff)(addrTemp)
+            */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lw(dataTempRegister, addrTempRegister, address.offset);
+
+            if (!imm.m_isPointer
+                && imm.m_value >= -32767 && imm.m_value <= 32768
+                && !m_fixedWidth)
+                m_assembler.addiu(dataTempRegister, dataTempRegister,
+                                  -imm.m_value);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.subu(dataTempRegister, dataTempRegister,
+                                 immTempRegister);
+            }
+            m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
+        }
+    }
+
+    void sub32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        sub32(dataTempRegister, dest);
+    }
+
+    void sub32(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        /*
+           li   addrTemp, address
+           li   immTemp, imm
+           lw   dataTemp, 0(addrTemp)
+           subu dataTemp, dataTemp, immTemp
+           sw   dataTemp, 0(addrTemp)
+        */
+        move(ImmPtr(address.m_ptr), addrTempRegister);
+        m_assembler.lw(dataTempRegister, addrTempRegister, 0);
+
+        if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
+            && !m_fixedWidth) {
+            m_assembler.addiu(dataTempRegister, dataTempRegister,
+                              -imm.m_value);
+        } else {
+            move(imm, immTempRegister);
+            m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
+        }
+        m_assembler.sw(dataTempRegister, addrTempRegister, 0);
+    }
+
+    void xor32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        m_assembler.xorInsn(dest, dest, dataTempRegister);
+    }
+
+    void xor32(RegisterID src, RegisterID dest)
+    {
+        m_assembler.xorInsn(dest, dest, src);
+    }
+
+    void xor32(TrustedImm32 imm, RegisterID dest)
+    {
+        /*
+            li  immTemp, imm
+            xor dest, dest, immTemp
+        */
+        move(imm, immTempRegister);
+        m_assembler.xorInsn(dest, dest, immTempRegister);
+    }
+
+    void load16SignExtend(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lh(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lh      dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lh(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load16ZeroExtend(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lhu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lhu     dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load16SignExtend(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lh      dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lh(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lh      dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lh(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load16ZeroExtend(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lhu     dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lhu     dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load8SignExtend(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lb(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lb      dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lb(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load8ZeroExtend(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lbu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lbu     dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load8SignExtend(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lb      dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lb(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lb      dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lb(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load8ZeroExtend(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lbu     dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lbu     dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void negDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.negd(dest, src);
+    }
+
+    void absDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.absd(dest, src);
+    }
+
+    void sqrtDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.sqrtd(dst, src);
+    }
+
+    // Memory access operations:
+    //
+    // Loads are of the form load(address, destination) and stores of the form
+    // store(source, address).  The source for a store may be an Imm32.  Address
+    // operand objects to loads and store will be implicitly constructed if a
+    // register is passed.
+
+    /* Need to use zero-extened load byte for load8.  */
+    void load8(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lbu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lbu     dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lbu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load32(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lw(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lw      dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lw(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load32(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lw      dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lw(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lw      dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lw(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32764
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                (Big-Endian)
+                lwl     dest, address.offset(addrTemp)
+                lwr     dest, address.offset+3(addrTemp)
+                (Little-Endian)
+                lwl     dest, address.offset+3(addrTemp)
+                lwr     dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+#if CPU(BIG_ENDIAN)
+            m_assembler.lwl(dest, addrTempRegister, address.offset);
+            m_assembler.lwr(dest, addrTempRegister, address.offset + 3);
+#else
+            m_assembler.lwl(dest, addrTempRegister, address.offset + 3);
+            m_assembler.lwr(dest, addrTempRegister, address.offset);
+
+#endif
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, address.offset >> 16
+                ori     immTemp, immTemp, address.offset & 0xffff
+                addu    addrTemp, addrTemp, immTemp
+                (Big-Endian)
+                lw      dest, 0(addrTemp)
+                lw      dest, 3(addrTemp)
+                (Little-Endian)
+                lw      dest, 3(addrTemp)
+                lw      dest, 0(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, address.offset >> 16);
+            m_assembler.ori(immTempRegister, immTempRegister, address.offset);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+#if CPU(BIG_ENDIAN)
+            m_assembler.lwl(dest, addrTempRegister, 0);
+            m_assembler.lwr(dest, addrTempRegister, 3);
+#else
+            m_assembler.lwl(dest, addrTempRegister, 3);
+            m_assembler.lwr(dest, addrTempRegister, 0);
+#endif
+        }
+    }
+
+    void load32(void* address, RegisterID dest)
+    {
+        /*
+            li  addrTemp, address
+            lw  dest, 0(addrTemp)
+        */
+        move(ImmPtr(address), addrTempRegister);
+        m_assembler.lw(dest, addrTempRegister, 0);
+    }
+
+    DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest)
+    {
+        m_fixedWidth = true;
+        /*
+            lui addrTemp, address.offset >> 16
+            ori addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            lw  dest, 0(addrTemp)
+        */
+        DataLabel32 dataLabel(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.lw(dest, addrTempRegister, 0);
+        m_fixedWidth = false;
+        return dataLabel;
+    }
+
+    void load64WithPatch(Address address, RegisterID tag, RegisterID payload, int tag_offset, int payload_offset)
+    {
+        m_fixedWidth = true;
+        /*
+            lui         addrTemp, address.offset >> 16
+            ori         addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            lw          tag, tag_offset(addrTemp)
+            lw          payload, payload_offset(addrTemp)
+        */
+        Label label(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.lw(tag, addrTempRegister, tag_offset);
+        m_assembler.lw(payload, addrTempRegister, payload_offset);
+        m_fixedWidth = false;
+    }
+
+    void store64WithPatch(Address address, RegisterID tag, RegisterID payload, int tag_offset, int payload_offset)
+    {
+        m_fixedWidth = true;
+        /*
+            lui         addrTemp, address.offset >> 16
+            ori         addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            sw          tag, tag_offset(addrTemp)
+            sw          payload, payload_offset(addrTemp)
+        */
+        Label label(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_fixedWidth = false;
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.sw(tag, addrTempRegister, tag_offset);
+        m_assembler.sw(payload, addrTempRegister, payload_offset);
+    }
+
+    void store64WithPatch(Address address, Imm32 tag, RegisterID payload, int tag_offset, int payload_offset)
+    {
+        m_fixedWidth = true;
+        /*
+            lui         addrTemp, address.offset >> 16
+            ori         addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            li          immTemp, tag
+            sw          immTemp, tag_offset(addrTemp)
+            sw          payload, payload_offset(addrTemp)
+        */
+        Label label(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_fixedWidth = false;
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        move(tag, immTempRegister);
+        m_assembler.sw(immTempRegister, addrTempRegister, tag_offset);
+        m_assembler.sw(payload, addrTempRegister, payload_offset);
+    }
+
+    void store64WithPatch(Address address, Imm32 tag, Imm32 payload, int tag_offset, int payload_offset)
+    {
+        m_fixedWidth = true;
+        /*
+            lui         addrTemp, address.offset >> 16
+            ori         addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            li          immTemp, tag
+            sw          immTemp, tag_offset(addrTemp)
+            li          immTemp, payload
+            sw          immTemp, payload_offset(addrTemp)
+        */
+        Label label(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_fixedWidth = false;
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        move(tag, immTempRegister);
+        m_assembler.sw(immTempRegister, addrTempRegister, tag_offset);
+        move(payload, immTempRegister);
+        m_assembler.sw(immTempRegister, addrTempRegister, payload_offset);
+    }
+
+    Label loadPtrWithPatchToLEA(Address address, RegisterID dest)
+    {
+        m_fixedWidth = true;
+        /*
+            lui         addrTemp, address.offset >> 16
+            ori         addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            lw          dest, 0(addrTemp)
+        */
+        Label label(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.lw(dest, addrTempRegister, 0);
+        m_fixedWidth = false;
+        return label;
+    }
+
+    /* Need to use zero-extened load half-word for load16.  */
+    void load16(ImplicitAddress address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.lhu(dest, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lhu     dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    /* Need to use zero-extened load half-word for load16.  */
+    void load16(BaseIndex address, RegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lhu     dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lhu     dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lhu(dest, addrTempRegister, address.offset);
+        }
+    }
+
+    DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
+    {
+        m_fixedWidth = true;
+        /*
+            lui addrTemp, address.offset >> 16
+            ori addrTemp, addrTemp, address.offset & 0xffff
+            addu        addrTemp, addrTemp, address.base
+            sw  src, 0(addrTemp)
+        */
+        DataLabel32 dataLabel(this);
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.sw(src, addrTempRegister, 0);
+        m_fixedWidth = false;
+        return dataLabel;
+    }
+
+    void store8(RegisterID src, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.sb(src, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sb      src, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sb(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store8(RegisterID src, BaseIndex address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                sb      src, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sb(src, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                sb      src, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.sb(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store8(TrustedImm32 imm, BaseIndex address)
+    {
+        if (!imm.m_isPointer && !imm.m_value)
+            store8(MIPSRegisters::zero, address);
+        else {
+            move(imm, immTempRegister);
+            store8(immTempRegister, address);
+        }
+    }
+
+    void store8(TrustedImm32 imm, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            if (!imm.m_isPointer && !imm.m_value)
+                m_assembler.sb(MIPSRegisters::zero, address.base,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sb(immTempRegister, address.base, address.offset);
+            }
+        } else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sb      immTemp, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+                m_assembler.sb(MIPSRegisters::zero, addrTempRegister,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sb(immTempRegister, addrTempRegister,
+                               address.offset);
+            }
+        }
+    }
+
+    void store8(RegisterID src, void* address)
+    {
+        /*
+            li  addrTemp, address
+            sb  src, 0(addrTemp)
+        */
+        move(ImmPtr(address), addrTempRegister);
+        m_assembler.sb(src, addrTempRegister, 0);
+    }
+
+    void store8(TrustedImm32 imm, void* address)
+    {
+        /*
+            li  immTemp, imm
+            li  addrTemp, address
+            sb  src, 0(addrTemp)
+        */
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0);
+        } else {
+            move(imm, immTempRegister);
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sb(immTempRegister, addrTempRegister, 0);
+        }
+    }
+
+    void store16(RegisterID src, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.sh(src, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sh      src, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sh(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store16(RegisterID src, BaseIndex address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                sh      src, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sh(src, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                sh      src, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.sh(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store16(TrustedImm32 imm, BaseIndex address)
+    {
+        if (!imm.m_isPointer && !imm.m_value)
+            store16(MIPSRegisters::zero, address);
+        else {
+            move(imm, immTempRegister);
+            store16(immTempRegister, address);
+        }
+    }
+
+    void store16(TrustedImm32 imm, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            if (!imm.m_isPointer && !imm.m_value)
+                m_assembler.sh(MIPSRegisters::zero, address.base,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sh(immTempRegister, address.base, address.offset);
+            }
+        } else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sh      immTemp, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+                m_assembler.sh(MIPSRegisters::zero, addrTempRegister,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sh(immTempRegister, addrTempRegister,
+                               address.offset);
+            }
+        }
+    }
+
+    void store16(RegisterID src, void* address)
+    {
+        /*
+            li  addrTemp, address
+            sh  src, 0(addrTemp)
+        */
+        move(ImmPtr(address), addrTempRegister);
+        m_assembler.sh(src, addrTempRegister, 0);
+    }
+
+    void store16(TrustedImm32 imm, void* address)
+    {
+        /*
+            li  immTemp, imm
+            li  addrTemp, address
+            sh  src, 0(addrTemp)
+        */
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sh(MIPSRegisters::zero, addrTempRegister, 0);
+        } else {
+            move(imm, immTempRegister);
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sh(immTempRegister, addrTempRegister, 0);
+        }
+    }
+
+    void store32(RegisterID src, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.sw(src, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sw      src, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sw(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store32(RegisterID src, BaseIndex address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                sw      src, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sw(src, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                sw      src, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.sw(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store32(TrustedImm32 imm, BaseIndex address)
+    {
+        if (!imm.m_isPointer && !imm.m_value)
+            store32(MIPSRegisters::zero, address);
+        else {
+            move(imm, immTempRegister);
+            store32(immTempRegister, address);
+        }
+    }
+
+    void store32(TrustedImm32 imm, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            if (!imm.m_isPointer && !imm.m_value)
+                m_assembler.sw(MIPSRegisters::zero, address.base,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sw(immTempRegister, address.base, address.offset);
+            }
+        } else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sw      immTemp, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+                m_assembler.sw(MIPSRegisters::zero, addrTempRegister,
+                               address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sw(immTempRegister, addrTempRegister,
+                               address.offset);
+            }
+        }
+    }
+
+    void store32(RegisterID src, void* address)
+    {
+        /*
+            li  addrTemp, address
+            sw  src, 0(addrTemp)
+        */
+        move(ImmPtr(address), addrTempRegister);
+        m_assembler.sw(src, addrTempRegister, 0);
+    }
+
+    void store32(TrustedImm32 imm, void* address)
+    {
+        /*
+            li  immTemp, imm
+            li  addrTemp, address
+            sw  src, 0(addrTemp)
+        */
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
+        } else {
+            move(imm, immTempRegister);
+            move(ImmPtr(address), addrTempRegister);
+            m_assembler.sw(immTempRegister, addrTempRegister, 0);
+        }
+    }
+
+    // Floating-point operations:
+
+    bool supportsFloatingPoint() const
+    {
+#if WTF_MIPS_DOUBLE_FLOAT
+        return true;
+#else
+        return false;
+#endif
+    }
+
+    bool supportsFloatingPointTruncate() const
+    {
+#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
+        return true;
+#else
+        return false;
+#endif
+    }
+
+    bool supportsFloatingPointSqrt() const
+    {
+#if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
+        return true;
+#else
+        return false;
+#endif
+    }
+
+    // Stack manipulation operations:
+    //
+    // The ABI is assumed to provide a stack abstraction to memory,
+    // containing machine word sized units of data.  Push and pop
+    // operations add and remove a single register sized unit of data
+    // to or from the stack.  Peek and poke operations read or write
+    // values on the stack, without moving the current stack position.
+
+    void pop(RegisterID dest)
+    {
+        m_assembler.lw(dest, MIPSRegisters::sp, 0);
+        m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, 4);
+    }
+
+    void push(RegisterID src)
+    {
+        m_assembler.addiu(MIPSRegisters::sp, MIPSRegisters::sp, -4);
+        m_assembler.sw(src, MIPSRegisters::sp, 0);
+    }
+
+    void push(Address address)
+    {
+        load32(address, dataTempRegister);
+        push(dataTempRegister);
+    }
+
+    void push(TrustedImm32 imm)
+    {
+        move(imm, immTempRegister);
+        push(immTempRegister);
+    }
+
+    // Register move operations:
+    //
+    // Move values in registers.
+
+    void move(TrustedImm32 imm, RegisterID dest)
+    {
+        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+            move(MIPSRegisters::zero, dest);
+        else if (imm.m_isPointer || m_fixedWidth) {
+            m_assembler.lui(dest, imm.m_value >> 16);
+            m_assembler.ori(dest, dest, imm.m_value);
+        } else
+            m_assembler.li(dest, imm.m_value);
+    }
+
+    void move(RegisterID src, RegisterID dest)
+    {
+        if (src != dest || m_fixedWidth)
+            m_assembler.move(dest, src);
+    }
+
+    void move(TrustedImmPtr imm, RegisterID dest)
+    {
+        move(Imm32(imm), dest);
+    }
+
+    void swap(RegisterID reg1, RegisterID reg2)
+    {
+        move(reg1, immTempRegister);
+        move(reg2, reg1);
+        move(immTempRegister, reg2);
+    }
+
+    void signExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+        if (src != dest || m_fixedWidth)
+            move(src, dest);
+    }
+
+    void zeroExtend32ToPtr(RegisterID src, RegisterID dest)
+    {
+        if (src != dest || m_fixedWidth)
+            move(src, dest);
+    }
+
+    // Forwards / external control flow operations:
+    //
+    // This set of jump and conditional branch operations return a Jump
+    // object which may linked at a later point, allow forwards jump,
+    // or jumps that will require external linkage (after the code has been
+    // relocated).
+    //
+    // For branches, signed <, >, <= and >= are denoted as l, g, le, and ge
+    // respecitvely, for unsigned comparisons the names b, a, be, and ae are
+    // used (representing the names 'below' and 'above').
+    //
+    // Operands to the comparision are provided in the expected order, e.g.
+    // jle32(reg1, Imm32(5)) will branch if the value held in reg1, when
+    // treated as a signed 32bit value, is less than or equal to 5.
+    //
+    // jz and jnz test whether the first operand is equal to zero, and take
+    // an optional second operand of a mask under which to perform the test.
+
+    Jump branch8(Condition cond, Address left, TrustedImm32 right)
+    {
+        // Make sure the immediate value is unsigned 8 bits.
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, dataTempRegister);
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branch32(Condition cond, RegisterID left, RegisterID right)
+    {
+        if (cond == Equal || cond == Zero)
+            return branchEqual(left, right);
+        if (cond == NotEqual || cond == NonZero)
+            return branchNotEqual(left, right);
+        if (cond == Above) {
+            m_assembler.sltu(cmpTempRegister, right, left);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == AboveOrEqual) {
+            m_assembler.sltu(cmpTempRegister, left, right);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Below) {
+            m_assembler.sltu(cmpTempRegister, left, right);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == BelowOrEqual) {
+            m_assembler.sltu(cmpTempRegister, right, left);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == GreaterThan) {
+            m_assembler.slt(cmpTempRegister, right, left);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == GreaterThanOrEqual) {
+            m_assembler.slt(cmpTempRegister, left, right);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == LessThan) {
+            m_assembler.slt(cmpTempRegister, left, right);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == LessThanOrEqual) {
+            m_assembler.slt(cmpTempRegister, right, left);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Overflow) {
+            /*
+                xor     cmpTemp, left, right
+                bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
+                nop
+                subu    cmpTemp, left, right
+                xor     cmpTemp, cmpTemp, left
+                bgez    No_overflow, cmpTemp    # same sign bit -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+              No_overflow:
+            */
+            m_assembler.xorInsn(cmpTempRegister, left, right);
+            m_assembler.bgez(cmpTempRegister, 11);
+            m_assembler.nop();
+            m_assembler.subu(cmpTempRegister, left, right);
+            m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
+            m_assembler.bgez(cmpTempRegister, 7);
+            m_assembler.nop();
+            return jump();
+        }
+        if (cond == Signed) {
+            m_assembler.subu(cmpTempRegister, left, right);
+            // Check if the result is negative.
+            m_assembler.slt(cmpTempRegister, cmpTempRegister,
+                            MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+
+        return Jump();
+    }
+
+    Jump branch32(Condition cond, RegisterID left, TrustedImm32 right)
+    {
+        move(right, immTempRegister);
+        return branch32(cond, left, immTempRegister);
+    }
+
+    Jump branch32(Condition cond, RegisterID left, Address right)
+    {
+        load32(right, dataTempRegister);
+        return branch32(cond, left, dataTempRegister);
+    }
+
+    Jump branch32(Condition cond, Address left, RegisterID right)
+    {
+        load32(left, dataTempRegister);
+        return branch32(cond, dataTempRegister, right);
+    }
+
+    Jump branch32(Condition cond, Address left, TrustedImm32 right)
+    {
+        load32(left, dataTempRegister);
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branch32(Condition cond, BaseIndex left, TrustedImm32 right)
+    {
+        load32(left, dataTempRegister);
+        // Be careful that the previous load32() uses immTempRegister.
+        // So, we need to put move() after load32().
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, TrustedImm32 right)
+    {
+        load32WithUnalignedHalfWords(left, dataTempRegister);
+        // Be careful that the previous load32WithUnalignedHalfWords()
+        // uses immTempRegister.
+        // So, we need to put move() after load32WithUnalignedHalfWords().
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
+    {
+        load32(left.m_ptr, dataTempRegister);
+        return branch32(cond, dataTempRegister, right);
+    }
+
+    Jump branch32(Condition cond, AbsoluteAddress left, TrustedImm32 right)
+    {
+        load32(left.m_ptr, dataTempRegister);
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branch16(Condition cond, BaseIndex left, RegisterID right)
+    {
+        load16(left, dataTempRegister);
+        return branch32(cond, dataTempRegister, right);
+    }
+
+    Jump branch16(Condition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(right.m_value & 0xFFFF0000));
+        load16(left, dataTempRegister);
+        // Be careful that the previous load16() uses immTempRegister.
+        // So, we need to put move() after load16().
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
+    Jump branchTest32(Condition cond, RegisterID reg, RegisterID mask)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        m_assembler.andInsn(cmpTempRegister, reg, mask);
+        if (cond == Zero)
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+    }
+
+    Jump branchTest32(Condition cond, RegisterID reg, Imm32 mask = Imm32(-1))
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        if (mask.m_value == -1 && !m_fixedWidth) {
+            if (cond == Zero)
+                return branchEqual(reg, MIPSRegisters::zero);
+            return branchNotEqual(reg, MIPSRegisters::zero);
+        }
+        move(mask, immTempRegister);
+        return branchTest32(cond, reg, immTempRegister);
+    }
+
+    Jump branchTest32(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    {
+        load32(address, dataTempRegister);
+        return branchTest32(cond, dataTempRegister, mask);
+    }
+
+    Jump branchTest32(Condition cond, BaseIndex address, Imm32 mask = Imm32(-1))
+    {
+        load32(address, dataTempRegister);
+        return branchTest32(cond, dataTempRegister, mask);
+    }
+
+    Jump branchTest8(Condition cond, Address address, Imm32 mask = Imm32(-1))
+    {
+        load8(address, dataTempRegister);
+        return branchTest32(cond, dataTempRegister, mask);
+    }
+
+    Jump jump()
+    {
+        return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
+    }
+
+    void jump(RegisterID target)
+    {
+        m_assembler.jr(target);
+        m_assembler.nop();
+    }
+
+    void jump(Address address)
+    {
+        m_fixedWidth = true;
+        load32(address, MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
+        m_assembler.nop();
+        m_fixedWidth = false;
+    }
+
+    void jump(BaseIndex address)
+    {
+        load32(address, MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
+        m_assembler.nop();
+    }
+
+    // Arithmetic control flow operations:
+    //
+    // This set of conditional branch operations branch based
+    // on the result of an arithmetic operation.  The operation
+    // is performed as normal, storing the result.
+    //
+    // * jz operations branch if the result is zero.
+    // * jo operations branch if the (signed) arithmetic
+    //   operation caused an overflow to occur.
+
+    Jump branchAdd32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            /*
+                move    dest, dataTemp
+                xor     cmpTemp, dataTemp, src
+                bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
+                addu    dest, dataTemp, src
+                xor     cmpTemp, dest, dataTemp
+                bgez    cmpTemp, No_overflow    # same sign big -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            move(dest, dataTempRegister);
+            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
+            m_assembler.bltz(cmpTempRegister, 10);
+            m_assembler.addu(dest, dataTempRegister, src);
+            m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
+            m_assembler.bgez(cmpTempRegister, 7);
+            m_assembler.nop();
+            return jump();
+        }
+        if (cond == Signed) {
+            add32(src, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            add32(src, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            add32(src, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
+    Jump branchAdd32(Condition cond, Imm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        return branchAdd32(cond, immTempRegister, dest);
+    }
+
+    Jump branchAdd32(Condition cond, Address src, RegisterID dest)
+    {
+        load32(src, immTempRegister);
+        return branchAdd32(cond, immTempRegister, dest);
+    }
+
+    Jump branchMul32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            /*
+                mult    src, dest
+                mfhi    dataTemp
+                mflo    dest
+                sra     addrTemp, dest, 31
+                beq     dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            m_assembler.mult(src, dest);
+            m_assembler.mfhi(dataTempRegister);
+            m_assembler.mflo(dest);
+            m_assembler.sra(addrTempRegister, dest, 31);
+            m_assembler.beq(dataTempRegister, addrTempRegister, 7);
+            m_assembler.nop();
+            return jump();
+        }
+        if (cond == Signed) {
+            mul32(src, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            mul32(src, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            mul32(src, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
+    Jump branchMul32(Condition cond, Imm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        move(src, dest);
+        return branchMul32(cond, immTempRegister, dest);
+    }
+
+    Jump branchSub32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            /*
+                move    dest, dataTemp
+                xor     cmpTemp, dataTemp, src
+                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
+                subu    dest, dataTemp, src
+                xor     cmpTemp, dest, dataTemp
+                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            move(dest, dataTempRegister);
+            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
+            m_assembler.bgez(cmpTempRegister, 10);
+            m_assembler.subu(dest, dataTempRegister, src);
+            m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
+            m_assembler.bgez(cmpTempRegister, 7);
+            m_assembler.nop();
+            return jump();
+        }
+        if (cond == Signed) {
+            sub32(src, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            sub32(src, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            sub32(src, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
+    Jump branchSub32(Condition cond, Imm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        return branchSub32(cond, immTempRegister, dest);
+    }
+
+    Jump branchSub32(Condition cond, Address src, RegisterID dest)
+    {
+        load32(src, immTempRegister);
+        return branchSub32(cond, immTempRegister, dest);
+    }
+
+    Jump branchSub32(Condition cond, Imm32 imm, Address dest)
+    {
+	// Save the original value at dest to dataTemp2Register
+        load32(dest, dataTemp2Register);
+
+        // Calculate the result and save it to dest
+        sub32(imm, dest);
+
+        return branchSub32(cond, imm, dataTemp2Register);
+    }
+
+    Jump branchOr32(Condition cond, RegisterID src, RegisterID dest)
+    {
+        ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero));
+        if (cond == Signed) {
+            or32(src, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            or32(src, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            or32(src, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
+    // Miscellaneous operations:
+
+    void breakpoint()
+    {
+        m_assembler.bkpt();
+    }
+
+    Call nearCall()
+    {
+        /* We need two words for relaxation.  */
+        m_assembler.nop();
+        m_assembler.nop();
+        m_assembler.jal();
+        m_assembler.nop();
+        return Call(m_assembler.newJmpSrc(), Call::LinkableNear);
+    }
+
+    Call call()
+    {
+        m_assembler.lui(MIPSRegisters::t9, 0);
+        m_assembler.ori(MIPSRegisters::t9, MIPSRegisters::t9, 0);
+        m_assembler.jalr(MIPSRegisters::t9);
+        m_assembler.nop();
+        return Call(m_assembler.newJmpSrc(), Call::Linkable);
+    }
+
+    Call call(RegisterID target)
+    {
+        m_assembler.jalr(target);
+        m_assembler.nop();
+        return Call(m_assembler.newJmpSrc(), Call::None);
+    }
+
+    Call call(Address address)
+    {
+        m_fixedWidth = true;
+        load32(address, MIPSRegisters::t9);
+        m_assembler.jalr(MIPSRegisters::t9);
+        m_assembler.nop();
+        m_fixedWidth = false;
+        return Call(m_assembler.newJmpSrc(), Call::None);
+    }
+
+    void ret()
+    {
+        m_assembler.jr(MIPSRegisters::ra);
+        m_assembler.nop();
+    }
+
+    void set8(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        set32(cond, left, right, dest);
+    }
+
+    void set8(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    {
+        move(right, immTempRegister);
+        set32(cond, left, immTempRegister, dest);
+    }
+
+    void set32(Condition cond, RegisterID left, RegisterID right, RegisterID dest)
+    {
+        if (cond == Equal || cond == Zero) {
+            m_assembler.xorInsn(dest, left, right);
+            m_assembler.sltiu(dest, dest, 1);
+        } else if (cond == NotEqual || cond == NonZero) {
+            m_assembler.xorInsn(dest, left, right);
+            m_assembler.sltu(dest, MIPSRegisters::zero, dest);
+        } else if (cond == Above)
+            m_assembler.sltu(dest, right, left);
+        else if (cond == AboveOrEqual) {
+            m_assembler.sltu(dest, left, right);
+            m_assembler.xori(dest, dest, 1);
+        } else if (cond == Below)
+            m_assembler.sltu(dest, left, right);
+        else if (cond == BelowOrEqual) {
+            m_assembler.sltu(dest, right, left);
+            m_assembler.xori(dest, dest, 1);
+        } else if (cond == GreaterThan)
+            m_assembler.slt(dest, right, left);
+        else if (cond == GreaterThanOrEqual) {
+            m_assembler.slt(dest, left, right);
+            m_assembler.xori(dest, dest, 1);
+        } else if (cond == LessThan)
+            m_assembler.slt(dest, left, right);
+        else if (cond == LessThanOrEqual) {
+            m_assembler.slt(dest, right, left);
+            m_assembler.xori(dest, dest, 1);
+        } else if (cond == Overflow) {
+            /*
+                xor     cmpTemp, left, right
+                bgez    Done, cmpTemp   # same sign bit -> no overflow
+                move    dest, 0
+                subu    cmpTemp, left, right
+                xor     cmpTemp, cmpTemp, left # diff sign bit -> overflow
+                slt     dest, cmpTemp, 0
+              Done:
+            */
+            m_assembler.xorInsn(cmpTempRegister, left, right);
+            m_assembler.bgez(cmpTempRegister, 4);
+            m_assembler.move(dest, MIPSRegisters::zero);
+            m_assembler.subu(cmpTempRegister, left, right);
+            m_assembler.xorInsn(cmpTempRegister, cmpTempRegister, left);
+            m_assembler.slt(dest, cmpTempRegister, MIPSRegisters::zero);
+        } else if (cond == Signed) {
+            m_assembler.subu(dest, left, right);
+            // Check if the result is negative.
+            m_assembler.slt(dest, dest, MIPSRegisters::zero);
+        }
+    }
+
+    void set32(Condition cond, Address left, Imm32 right, RegisterID dest)
+    {
+        load32(left, dataTempRegister);
+        move(right, immTempRegister);
+        set32(cond, dataTempRegister, immTempRegister, dest);
+    }
+
+    void set32(Condition cond, RegisterID left, Imm32 right, RegisterID dest)
+    {
+        move(right, immTempRegister);
+        set32(cond, left, immTempRegister, dest);
+    }
+
+    void set32(Condition cond, Address left, RegisterID right, RegisterID dest)
+    {
+        load32(left, immTempRegister);
+        set32(cond, immTempRegister, right, dest);
+    }
+
+    void set32(Condition cond, RegisterID left, Address right, RegisterID dest)
+    {
+        load32(right, immTempRegister);
+        set32(cond, left, immTempRegister, dest);
+    }
+
+    void setTest8(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        load8(address, dataTempRegister);
+        if (mask.m_value == -1 && !m_fixedWidth) {
+            if (cond == Zero)
+                m_assembler.sltiu(dest, dataTempRegister, 1);
+            else
+                m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
+        } else {
+            move(mask, immTempRegister);
+            m_assembler.andInsn(cmpTempRegister, dataTempRegister,
+                                immTempRegister);
+            if (cond == Zero)
+                m_assembler.sltiu(dest, cmpTempRegister, 1);
+            else
+                m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
+        }
+    }
+
+    void setTest32(Condition cond, Address address, Imm32 mask, RegisterID dest)
+    {
+        ASSERT((cond == Zero) || (cond == NonZero));
+        load32(address, dataTempRegister);
+        if (mask.m_value == -1 && !m_fixedWidth) {
+            if (cond == Zero)
+                m_assembler.sltiu(dest, dataTempRegister, 1);
+            else
+                m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
+        } else {
+            move(mask, immTempRegister);
+            m_assembler.andInsn(cmpTempRegister, dataTempRegister,
+                                immTempRegister);
+            if (cond == Zero)
+                m_assembler.sltiu(dest, cmpTempRegister, 1);
+            else
+                m_assembler.sltu(dest, MIPSRegisters::zero, cmpTempRegister);
+        }
+    }
+
+    DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dest)
+    {
+        m_fixedWidth = true;
+        DataLabel32 label(this);
+        move(imm, dest);
+        m_fixedWidth = false;
+        return label;
+    }
+
+    DataLabelPtr moveWithPatch(TrustedImmPtr initialValue, RegisterID dest)
+    {
+        m_fixedWidth = true;
+        DataLabelPtr label(this);
+        move(initialValue, dest);
+        m_fixedWidth = false;
+        return label;
+    }
+
+    Jump branch32WithPatch(Condition cond, RegisterID left, TrustedImm32 right, DataLabel32& dataLabel)
+    {
+        m_fixedWidth = true;
+        dataLabel = moveWithPatch(right, immTempRegister);
+        Jump temp = branch32(cond, left, immTempRegister);
+        m_fixedWidth = false;
+        return temp;
+    }
+
+    Jump branch32FixedLength(Condition cond, RegisterID left, TrustedImm32 right)
+    {
+        m_fixedWidth = true;
+        move(right, immTempRegister);
+        Jump temp = branch32(cond, left, immTempRegister);
+        m_fixedWidth = false;
+        return temp;
+    }
+
+    Jump branch32WithPatch(Condition cond, Address left, TrustedImm32 right, DataLabel32& dataLabel)
+    {
+        m_fixedWidth = true;
+        load32(left, dataTempRegister);
+        dataLabel = moveWithPatch(right, immTempRegister);
+        Jump temp = branch32(cond, dataTempRegister, immTempRegister);
+        m_fixedWidth = false;
+        return temp;
+    }
+
+    Jump branchPtrWithPatch(Condition cond, RegisterID left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    {
+        m_fixedWidth = true;
+        dataLabel = moveWithPatch(initialRightValue, immTempRegister);
+        Jump temp = branch32(cond, left, immTempRegister);
+        m_fixedWidth = false;
+        return temp;
+    }
+
+    Jump branchPtrWithPatch(Condition cond, Address left, DataLabelPtr& dataLabel, ImmPtr initialRightValue = ImmPtr(0))
+    {
+        m_fixedWidth = true;
+        load32(left, dataTempRegister);
+        dataLabel = moveWithPatch(initialRightValue, immTempRegister);
+        Jump temp = branch32(cond, dataTempRegister, immTempRegister);
+        m_fixedWidth = false;
+        return temp;
+    }
+
+    DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address)
+    {
+        m_fixedWidth = true;
+        DataLabelPtr dataLabel = moveWithPatch(initialValue, dataTempRegister);
+        store32(dataTempRegister, address);
+        m_fixedWidth = false;
+        return dataLabel;
+    }
+
+    DataLabelPtr storePtrWithPatch(ImplicitAddress address)
+    {
+        return storePtrWithPatch(ImmPtr(0), address);
+    }
+
+    Call tailRecursiveCall()
+    {
+        // Like a normal call, but don't update the returned address register
+        m_fixedWidth = true;
+        move(Imm32(0), MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
+        m_assembler.nop();
+        m_fixedWidth = false;
+        return Call(m_assembler.newJmpSrc(), Call::Linkable);
+    }
+
+    Call makeTailRecursiveCall(Jump oldJump)
+    {
+        oldJump.link(this);
+        return tailRecursiveCall();
+    }
+
+    void moveDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.movd(dest, src);
+    }
+
+    void loadFloat(ImplicitAddress address, FPRegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            m_assembler.lwc1(dest, address.base, address.offset);
+            m_assembler.cvtds(dest, dest);
+        } else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                lwc1    dest, (offset & 0xffff)(addrTemp)
+                cvt.d.s dest, dest
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lwc1(dest, addrTempRegister, address.offset);
+            m_assembler.cvtds(dest, dest);
+        }
+    }
+
+    void loadFloat(BaseIndex address, FPRegisterID dest)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lwc1    dest, address.offset(addrTemp)
+                cvt.d.s dest, dest
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lwc1(dest, addrTempRegister, address.offset);
+            m_assembler.cvtds(dest, dest);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lwc1    dest, (address.offset & 0xffff)(addrTemp)
+                cvt.d.s dest, dest
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lwc1(dest, addrTempRegister, address.offset);
+            m_assembler.cvtds(dest, dest);
+        }
+    }
+
+    DataLabelPtr loadFloat(const void* address, FPRegisterID dest)
+    {
+        DataLabelPtr label = moveWithPatch(ImmPtr(address), addrTempRegister);
+        /*
+            lwc1        dest, 0(addrTemp)
+            cvt.d.s     dest, dest
+        */
+        m_assembler.lwc1(dest, addrTempRegister, 0);
+        m_assembler.cvtds(dest, dest);
+        return label;
+    }
+
+    void loadDouble(ImplicitAddress address, FPRegisterID dest)
+    {
+#if WTF_MIPS_ISA(1)
+        /*
+            li          addrTemp, address.offset
+            addu        addrTemp, addrTemp, base
+            lwc1        dest, 0(addrTemp)
+            lwc1        dest+1, 4(addrTemp)
+         */
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.lwc1(dest, addrTempRegister, 0);
+        m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
+#else
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            m_assembler.ldc1(dest, address.base, address.offset);
+        } else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                ldc1    dest, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.ldc1(dest, addrTempRegister, address.offset);
+        }
+#endif
+    }
+
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+#if WTF_MIPS_ISA(1)
+        if (address.offset >= -32768 && address.offset <= 32763
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lwc1    dest, address.offset(addrTemp)
+                lwc1    dest+1, address.offset+4(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lwc1(dest, addrTempRegister, address.offset);
+            m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 4);
+        } else {
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                li      immTemp, address.offset
+                addu    addrTemp, addrTemp, immTemp
+                lwc1    dest, 0(addrTemp)
+                lwc1    dest+1, 4(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.li(immTempRegister, address.offset);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.lwc1(dest, addrTempRegister, 0);
+            m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
+#else
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                ldc1    dest, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.ldc1(dest, addrTempRegister, address.offset);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                ldc1    dest, (address.offset & 0xffff)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister,
+                             immTempRegister);
+            m_assembler.ldc1(dest, addrTempRegister, address.offset);
+        }
+#endif
+    }
+
+    DataLabelPtr loadDouble(const void* address, FPRegisterID dest)
+    {
+        DataLabelPtr label = moveWithPatch(ImmPtr(address), addrTempRegister);
+#if WTF_MIPS_ISA(1)
+        /*
+            lwc1        dest, 0(addrTemp)
+            lwc1        dest+1, 4(addrTemp)
+         */
+        m_assembler.lwc1(dest, addrTempRegister, 0);
+        m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
+#else
+        /*
+            ldc1        dest, 0(addrTemp)
+        */
+        m_assembler.ldc1(dest, addrTempRegister, 0);
+#endif
+        return label;
+    }
+
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        lea(address, addrTempRegister);
+        m_assembler.swc1(src, addrTempRegister, 0);
+    }
+
+    void storeFloat(FPRegisterID src, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.swc1(src, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                swc1    src, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.swc1(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void storeFloat(ImmDouble imm, Address address)
+    {
+        union {
+            float f;
+            uint32_t u32;
+        } u;
+        u.f = imm.u.d;
+        store32(Imm32(u.u32), address);
+    }
+
+    void storeFloat(ImmDouble imm, BaseIndex address)
+    {
+        union {
+            float f;
+            uint32_t u32;
+        } u;
+        u.f = imm.u.d;
+        store32(Imm32(u.u32), address);
+    }
+
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+        lea(address, addrTempRegister);
+#if WTF_MIPS_ISA(1)
+        m_assembler.swc1(src, addrTempRegister, 0);
+        m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
+#else
+        m_assembler.sdc1(src, addrTempRegister, 0);
+#endif
+    }
+
+    void storeDouble(FPRegisterID src, ImplicitAddress address)
+    {
+#if WTF_MIPS_ISA(1)
+        /*
+            li          addrTemp, address.offset
+            addu        addrTemp, addrTemp, base
+            swc1        dest, 0(addrTemp)
+            swc1        dest+1, 4(addrTemp)
+         */
+        move(Imm32(address.offset), addrTempRegister);
+        m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+        m_assembler.swc1(src, addrTempRegister, 0);
+        m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
+#else
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth)
+            m_assembler.sdc1(src, address.base, address.offset);
+        else {
+            /*
+                lui     addrTemp, (offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, base
+                sdc1    src, (offset & 0xffff)(addrTemp)
+              */
+            m_assembler.lui(addrTempRegister, (address.offset + 0x8000) >> 16);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sdc1(src, addrTempRegister, address.offset);
+        }
+#endif
+    }
+
+    void storeDouble(ImmDouble imm, Address address)
+    {
+#if CPU(BIG_ENDIAN)
+        store32(Imm32(imm.u.s.msb), address);
+        store32(Imm32(imm.u.s.lsb), Address(address.base, address.offset + 4));
+#else
+        store32(Imm32(imm.u.s.lsb), address);
+        store32(Imm32(imm.u.s.msb), Address(address.base, address.offset + 4));
+#endif
+    }
+
+    void storeDouble(ImmDouble imm, BaseIndex address)
+    {
+#if CPU(BIG_ENDIAN)
+        store32(Imm32(imm.u.s.msb), address);
+        store32(Imm32(imm.u.s.lsb),
+                BaseIndex(address.base, address.index, address.scale, address.offset + 4));
+#else
+        store32(Imm32(imm.u.s.lsb), address);
+        store32(Imm32(imm.u.s.msb),
+                BaseIndex(address.base, address.index, address.scale, address.offset + 4));
+#endif
+    }
+
+    void addDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.addd(dest, dest, src);
+    }
+
+    void addDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, fpTempRegister);
+        m_assembler.addd(dest, dest, fpTempRegister);
+    }
+
+    void subDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.subd(dest, dest, src);
+    }
+
+    void subDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, fpTempRegister);
+        m_assembler.subd(dest, dest, fpTempRegister);
+    }
+
+    void mulDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.muld(dest, dest, src);
+    }
+
+    void mulDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, fpTempRegister);
+        m_assembler.muld(dest, dest, fpTempRegister);
+    }
+
+    void divDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.divd(dest, dest, src);
+    }
+
+    void convertUInt32ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        /*
+                mtc1    src, fpTemp
+                bgez    src, OK		// Test the sign bit
+                cvt.d.w dest, fpTemp
+
+                // Store 0x41F0000000000000 to the fpTemp.
+                // Then, add fpTemp to dest to compenstate the negative value.
+                mtc1    zero, fpTemp
+                lui     dataTemp, 0x41F0
+                mtc1    dataTemp, fpTemp + 1
+                add.d   dest, dest, fpTemp
+            OK:
+        */
+        m_assembler.mtc1(src, fpTempRegister);
+        m_assembler.bgez(src, 5);
+        m_assembler.cvtdw(dest, fpTempRegister);
+
+        m_assembler.mtc1(MIPSRegisters::zero, fpTempRegister);
+        m_assembler.lui(dataTempRegister, 0x41F0);
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mthc1(dataTempRegister, fpTempRegister);
+#else
+        m_assembler.mtc1(dataTempRegister, FPRegisterID(fpTempRegister + 1));
+#endif
+        m_assembler.addd(dest, dest, fpTempRegister);
+    }
+
+    void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
+    {
+        m_assembler.mtc1(src, fpTempRegister);
+        m_assembler.cvtdw(dest, fpTempRegister);
+    }
+
+    void convertInt32ToDouble(Address src, FPRegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        m_assembler.mtc1(dataTempRegister, fpTempRegister);
+        m_assembler.cvtdw(dest, fpTempRegister);
+    }
+
+    void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest)
+    {
+        load32(src.m_ptr, dataTempRegister);
+        m_assembler.mtc1(dataTempRegister, fpTempRegister);
+        m_assembler.cvtdw(dest, fpTempRegister);
+    }
+
+    void insertRelaxationWords()
+    {
+        /* We need four words for relaxation. */
+        m_assembler.beq(MIPSRegisters::zero, MIPSRegisters::zero, 3); // Jump over nops;
+        m_assembler.nop();
+        m_assembler.nop();
+        m_assembler.nop();
+    }
+
+    Jump branchTrue()
+    {
+        m_assembler.appendJump();
+        m_assembler.bc1t();
+        m_assembler.nop();
+        insertRelaxationWords();
+        return Jump(m_assembler.newJmpSrc());
+    }
+
+    Jump branchFalse()
+    {
+        m_assembler.appendJump();
+        m_assembler.bc1f();
+        m_assembler.nop();
+        insertRelaxationWords();
+        return Jump(m_assembler.newJmpSrc());
+    }
+
+    Jump branchEqual(RegisterID rs, RegisterID rt)
+    {
+        m_assembler.appendJump();
+        m_assembler.beq(rs, rt, 0);
+        m_assembler.nop();
+        insertRelaxationWords();
+        return Jump(m_assembler.newJmpSrc());
+    }
+
+    Jump branchNotEqual(RegisterID rs, RegisterID rt)
+    {
+        m_assembler.appendJump();
+        m_assembler.bne(rs, rt, 0);
+        m_assembler.nop();
+        insertRelaxationWords();
+        return Jump(m_assembler.newJmpSrc());
+    }
+
+    void fastStoreDouble(FPRegisterID src, RegisterID lo, RegisterID hi)
+    {
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mfc1(lo, src);
+        m_assembler.mfhc1(hi, src);
+#else
+        m_assembler.mfc1(lo, src);
+        m_assembler.mfc1(hi, FPRegisterID(src + 1));
+#endif
+    }
+
+    void fastLoadDouble(RegisterID lo, RegisterID hi, FPRegisterID fpReg)
+    {
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mtc1(lo, fpReg);
+        m_assembler.mthc1(hi, fpReg);
+#else
+        m_assembler.mtc1(lo, fpReg);
+        m_assembler.mtc1(hi, FPRegisterID(fpReg + 1));
+#endif
+    }
+
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.cvtsd(dest, src);
+    }
+
+    Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right)
+    {
+        if (cond == DoubleEqual) {
+            m_assembler.ceqd(left, right);
+            return branchTrue();
+        }
+        if (cond == DoubleNotEqual) {
+            m_assembler.cueqd(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleGreaterThan) {
+            m_assembler.cngtd(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleGreaterThanOrEqual) {
+            m_assembler.cnged(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleLessThan) {
+            m_assembler.cltd(left, right);
+            return branchTrue();
+        }
+        if (cond == DoubleLessThanOrEqual) {
+            m_assembler.cled(left, right);
+            return branchTrue();
+        }
+        if (cond == DoubleEqualOrUnordered) {
+            m_assembler.cueqd(left, right);
+            return branchTrue();
+        }
+        if (cond == DoubleNotEqualOrUnordered) {
+            m_assembler.ceqd(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleGreaterThanOrUnordered) {
+            m_assembler.coled(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleGreaterThanOrEqualOrUnordered) {
+            m_assembler.coltd(left, right);
+            return branchFalse(); // false
+        }
+        if (cond == DoubleLessThanOrUnordered) {
+            m_assembler.cultd(left, right);
+            return branchTrue();
+        }
+        if (cond == DoubleLessThanOrEqualOrUnordered) {
+            m_assembler.culed(left, right);
+            return branchTrue();
+        }
+        ASSERT(0);
+
+        return Jump();
+    }
+
+    // Truncates 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, INT_MAX 0x7fffffff).
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        m_assembler.truncwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+        return branch32(Equal, dest, Imm32(0x7fffffff));
+    }
+
+    // Convert 'src' to an integer, and places the resulting 'dest'.
+    // If the result is not representable as a 32 bit value, branch.
+    // May also branch for some values that are representable in 32 bits
+    // (specifically, in this case, 0).
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp)
+    {
+        m_assembler.cvtwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+
+        // If the result is zero, it might have been -0.0, and the double comparison won't catch this!
+        failureCases.append(branch32(Equal, dest, MIPSRegisters::zero));
+
+        // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump.
+        convertInt32ToDouble(dest, fpTemp);
+        failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fpTemp, src));
+    }
+
+    void zeroDouble(FPRegisterID dest)
+    {
+#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
+        m_assembler.mtc1(MIPSRegisters::zero, dest);
+        m_assembler.mthc1(MIPSRegisters::zero, dest);
+#else
+        m_assembler.mtc1(MIPSRegisters::zero, dest);
+        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(dest + 1));
+#endif
+    }
+
+private:
+    // If m_fixedWidth is true, we will generate a fixed number of instructions.
+    // Otherwise, we can emit any number of instructions.
+    bool m_fixedWidth;
+
+    friend class LinkBuffer;
+    friend class RepatchBuffer;
+
+    static void linkCall(void* code, Call call, FunctionPtr function)
+    {
+        MIPSAssembler::linkCall(code, call.m_jmp, function.value());
+    }
+
+    static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)
+    {
+        MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
+    }
+
+    static void repatchCall(CodeLocationCall call, FunctionPtr destination)
+    {
+        MIPSAssembler::relinkCall(call.dataLocation(), destination.executableAddress());
+    }
+
+};
+
+}
+
+#endif // ENABLE(ASSEMBLER) && CPU(MIPS)
+
+#endif // MacroAssemblerMIPS_h
--- a/js/src/assembler/wtf/Platform.h
+++ b/js/src/assembler/wtf/Platform.h
@@ -1023,17 +1023,17 @@
 
 /* Disable the JIT on versions of GCC prior to 4.1 */
 #if !defined(ENABLE_JIT) && WTF_COMPILER_GCC && !GCC_VERSION_AT_LEAST(4, 1, 0)
 #define ENABLE_JIT 0
 #endif
 
 /* The JIT is enabled by default on all x86, x64-64, ARM platforms. */
 #if !defined(ENABLE_JIT) \
-    && (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_SPARC32) \
+    && (WTF_CPU_X86 || WTF_CPU_X86_64 || WTF_CPU_ARM || WTF_CPU_SPARC32 || WTF_CPU_MIPS) \
     && (WTF_OS_DARWIN || !WTF_COMPILER_GCC || GCC_VERSION_AT_LEAST(4, 1, 0)) \
     && !WTF_OS_WINCE
 #define ENABLE_JIT 1
 #endif
 
 /* Currently only implemented for JSVALUE64, only tested on WTF_PLATFORM_MAC */
 #if ENABLE_JIT && WTF_USE_JSVALUE64 && WTF_PLATFORM_MAC
 #define ENABLE_DFG_JIT 1
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2806,16 +2806,24 @@ arm*-*)
 sparc*-*)
     ENABLE_METHODJIT=1
     ENABLE_MONOIC=1
     ENABLE_POLYIC=1
     ENABLE_METHODJIT_TYPED_ARRAY=1
     AC_DEFINE(JS_CPU_SPARC)
     AC_DEFINE(JS_NUNBOX32)
     ;;
+mips*-*)
+    ENABLE_METHODJIT=1
+    ENABLE_MONOIC=1
+    ENABLE_POLYIC=1
+    ENABLE_METHODJIT_TYPED_ARRAY=1
+    AC_DEFINE(JS_CPU_MIPS)
+    AC_DEFINE(JS_NUNBOX32)
+    ;;
 esac
 
 MOZ_ARG_DISABLE_BOOL(methodjit,
 [  --disable-methodjit           Disable method JIT support],
   ENABLE_METHODJIT= )
 
 MOZ_ARG_DISABLE_BOOL(monoic,
 [  --disable-monoic      Disable use of MICs by JIT compiler],
--- a/js/src/jitstats.tbl
+++ b/js/src/jitstats.tbl
@@ -80,16 +80,17 @@ RECORDER_JITSTAT(noCompatInnerTrees, "un
 RECORDER_JITSTAT(blacklisted, "blacklisted")
 MONITOR_JITSTAT(cacheFlushed, "flushed")
 JITSTAT(archIsIA32)
 JITSTAT(archIsAMD64)
 JITSTAT(archIs64BIT)
 JITSTAT(archIsARM)
 JITSTAT(archIsSPARC)
 JITSTAT(archIsPPC)
+JITSTAT(archIsMIPS)
 
 #ifdef DEFINED_MONITOR_JITSTAT
 #undef DEFINED_MONITOR_JITSTAT
 #undef MONITOR_JITSTAT
 #endif
 
 #ifdef DEFINED_RECORDER_JITSTAT
 #undef DEFINED_RECORDER_JITSTAT
--- a/js/src/jsnum.h
+++ b/js/src/jsnum.h
@@ -87,17 +87,21 @@ typedef union jsdpun {
     jsdouble d;
 } jsdpun;
 
 static inline int
 JSDOUBLE_IS_NaN(jsdouble d)
 {
     jsdpun u;
     u.d = d;
+#if defined(mips) || defined(__mips__) || defined(MIPS) || defined(_MIPS_)
+    return (u.u64 & ~JSDOUBLE_SIGNBIT) > JSDOUBLE_EXPMASK;
+#else
     return (u.s.hi & JSDOUBLE_HI32_NAN) == JSDOUBLE_HI32_NAN;
+#endif
 }
 
 static inline int
 JSDOUBLE_IS_FINITE(jsdouble d)
 {
     /* -0 is finite. NaNs are not. */
     jsdpun u;
     u.d = d;
--- a/js/src/methodjit/BaseAssembler.h
+++ b/js/src/methodjit/BaseAssembler.h
@@ -169,16 +169,20 @@ static const JSC::MacroAssembler::Regist
 #elif defined(JS_CPU_ARM)
 static const JSC::MacroAssembler::RegisterID JSReturnReg_Type  = JSC::ARMRegisters::r5;
 static const JSC::MacroAssembler::RegisterID JSReturnReg_Data  = JSC::ARMRegisters::r4;
 static const JSC::MacroAssembler::RegisterID JSParamReg_Argc   = JSC::ARMRegisters::r1;
 #elif defined(JS_CPU_SPARC)
 static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::SparcRegisters::l2;
 static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::SparcRegisters::l3;
 static const JSC::MacroAssembler::RegisterID JSParamReg_Argc  = JSC::SparcRegisters::l4;
+#elif defined(JS_CPU_MIPS)
+static const JSC::MacroAssembler::RegisterID JSReturnReg_Type = JSC::MIPSRegisters::a0;
+static const JSC::MacroAssembler::RegisterID JSReturnReg_Data = JSC::MIPSRegisters::a2;
+static const JSC::MacroAssembler::RegisterID JSParamReg_Argc  = JSC::MIPSRegisters::a1;
 #endif
 
     size_t distanceOf(Label l) {
         return differenceBetween(startLabel, l);
     }
 
     void loadPtrFromImm(void *ptr, RegisterID reg) {
         loadPtr(ptr, reg);
@@ -278,17 +282,17 @@ static const JSC::MacroAssembler::Regist
     }
 
     void negateDouble(FPRegisterID fpreg)
     {
 #if defined JS_CPU_X86 || defined JS_CPU_X64
         static const uint64_t DoubleNegMask = 0x8000000000000000ULL;
         loadDouble(&DoubleNegMask, Registers::FPConversionTemp);
         xorDouble(Registers::FPConversionTemp, fpreg);
-#elif defined JS_CPU_ARM || defined JS_CPU_SPARC
+#elif defined JS_CPU_ARM || defined JS_CPU_SPARC || defined JS_CPU_MIPS
         negDouble(fpreg, fpreg);
 #endif
     }
 
     /* Prepare for a call that might THROW. */
     void *getFallibleCallTarget(void *fun) {
 #ifdef JS_CPU_ARM
         /*
@@ -313,16 +317,23 @@ static const JSC::MacroAssembler::Regist
          * target address located on stack without veneer. We record the return
          * address and jump to that address after call return to jited code. The
          * reason we take veneer back is jited code maybe released when
          * exceptions happened. That will make the call have no chance to return
          * back to jited code.
          */
         moveWithPatch(Imm32(intptr_t(fun)), JSC::SparcRegisters::i0);
         return JS_FUNC_TO_DATA_PTR(void *, JaegerStubVeneer);
+#elif defined(JS_CPU_MIPS)
+        /*
+         * For MIPS, we need to call JaegerStubVeneer by passing
+         * the real target address in v0.
+         */
+        moveWithPatch(Imm32(intptr_t(fun)), JSC::MIPSRegisters::v0);
+        return JS_FUNC_TO_DATA_PTR(void *, JaegerStubVeneer);
 #else
         /*
          * Architectures that push the return address to an easily-determined
          * location on the stack can hijack C++'s return mechanism by overwriting
          * that address, so a veneer is not required.
          */
         return fun;
 #endif
@@ -353,20 +364,24 @@ static const JSC::MacroAssembler::Regist
 
     // Similar to freeStack(), but combines it with a pop().
     void restoreReg(RegisterID reg) {
         JS_ASSERT(extraStackSpace >= sizeof(void *));
         extraStackSpace -= sizeof(void *);
         pop(reg);
     }
 
+#if defined JS_CPU_MIPS
+    static const uint32_t StackAlignment = 8;
+#else
     static const uint32_t StackAlignment = 16;
+#endif
 
     static inline uint32_t alignForCall(uint32_t stackBytes) {
-#if defined(JS_CPU_X86) || defined(JS_CPU_X64)
+#if defined(JS_CPU_X86) || defined(JS_CPU_X64) || defined(JS_CPU_MIPS)
         // If StackAlignment is a power of two, % is just two shifts.
         // 16 - (x % 16) gives alignment, extra % 16 handles total == 0.
         return align(stackBytes, StackAlignment);
 #else
         return 0;
 #endif
     }
 
--- a/js/src/methodjit/Compiler.cpp
+++ b/js/src/methodjit/Compiler.cpp
@@ -939,18 +939,24 @@ mjit::Compiler::finishThisUp(JITScript *
 
 #ifdef JS_CPU_ARM
     masm.forceFlushConstantPool();
     stubcc.masm.forceFlushConstantPool();
 #endif
     JaegerSpew(JSpew_Insns, "## Fast code (masm) size = %lu, Slow code (stubcc) size = %lu.\n",
                (unsigned long) masm.size(), (unsigned long) stubcc.size());
 
+    /* To make inlineDoubles and oolDoubles aligned to sizeof(double) bytes,
+       MIPS adds extra sizeof(double) bytes to codeSize.  */
     size_t codeSize = masm.size() +
+#if defined(JS_CPU_MIPS) 
+                      stubcc.size() + sizeof(double) +
+#else
                       stubcc.size() +
+#endif
                       (masm.numDoubles() * sizeof(double)) +
                       (stubcc.masm.numDoubles() * sizeof(double)) +
                       jumpTableOffsets.length() * sizeof(void *);
 
     JSC::ExecutablePool *execPool;
     uint8_t *result = (uint8_t *)script->compartment()->jaegerCompartment()->execAlloc()->
                     alloc(codeSize, &execPool, JSC::METHOD_CODE);
     if (!result) {
@@ -1362,17 +1368,26 @@ mjit::Compiler::finishThisUp(JITScript *
 
     JS_ASSERT(size_t(cursor - (uint8_t*)jit) == dataSize);
     /* Pass in NULL here -- we don't want slop bytes to be counted. */
     JS_ASSERT(jit->scriptDataSize(NULL) == dataSize);
 
     /* Link fast and slow paths together. */
     stubcc.fixCrossJumps(result, masm.size(), masm.size() + stubcc.size());
 
+#if defined(JS_CPU_MIPS)
+    /* Make sure doubleOffset is aligned to sizeof(double) bytes.  */ 
+    size_t doubleOffset = (((size_t)result + masm.size() + stubcc.size() +
+                            sizeof(double) - 1) & (~(sizeof(double) - 1))) -
+                          (size_t)result;
+    JS_ASSERT((((size_t)result + doubleOffset) & 7) == 0);
+#else
     size_t doubleOffset = masm.size() + stubcc.size();
+#endif
+
     double *inlineDoubles = (double *) (result + doubleOffset);
     double *oolDoubles = (double*) (result + doubleOffset +
                                     masm.numDoubles() * sizeof(double));
 
     /* Generate jump tables. */
     void **jumpVec = (void **)(oolDoubles + stubcc.masm.numDoubles());
 
     for (size_t i = 0; i < jumpTableOffsets.length(); i++) {
@@ -3393,17 +3408,17 @@ mjit::Compiler::interruptCheckHelper()
          * we can skip this, as there is only one flag to poll.
          */
 #ifdef JS_THREADSAFE
         void *interrupt = (void*) &cx->runtime->interruptCounter;
 #else
         void *interrupt = (void*) &JS_THREAD_DATA(cx)->interruptFlags;
 #endif
 
-#if defined(JS_CPU_X86) || defined(JS_CPU_ARM)
+#if defined(JS_CPU_X86) || defined(JS_CPU_ARM) || defined(JS_CPU_MIPS)
         jump = masm.branch32(Assembler::NotEqual, AbsoluteAddress(interrupt), Imm32(0));
 #else
         /* Handle processors that can't load from absolute addresses. */
         RegisterID reg = frame.allocReg();
         masm.move(ImmPtr(interrupt), reg);
         jump = masm.branchTest32(Assembler::NonZero, Address(reg, 0));
         frame.freeReg(reg);
 #endif
--- a/js/src/methodjit/FastOps.cpp
+++ b/js/src/methodjit/FastOps.cpp
@@ -2319,16 +2319,22 @@ mjit::Compiler::jsop_stricteq(JSOp op)
         masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType1), result1);
         masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType2), result);
         if(op == JSOP_STRICTEQ) {
             masm.and32(result1, result);
         } else {
             masm.or32(result1, result);
         }
         frame.freeReg(result1);
+#elif defined(JS_CPU_MIPS)
+        /* On MIPS the result 0.0/0.0 is 0x7FF7FFFF.
+           We need to manually set it to 0x7FF80000. */
+        static const int ShiftedCanonicalNaNType = 0x7FF80000 << 1;
+        masm.setShiftedCanonicalNaN(treg, treg);
+        masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType), result);
 #elif !defined(JS_CPU_X64)
         static const int ShiftedCanonicalNaNType = 0x7FF80000 << 1;
         masm.setPtr(oppositeCond, treg, Imm32(ShiftedCanonicalNaNType), result);
 #else
         static const void *ShiftedCanonicalNaNType = (void *)(0x7FF8000000000000 << 1);
         masm.move(ImmPtr(ShiftedCanonicalNaNType), Registers::ScratchReg);
         masm.setPtr(oppositeCond, treg, Registers::ScratchReg, result);
 #endif
--- a/js/src/methodjit/ICRepatcher.h
+++ b/js/src/methodjit/ICRepatcher.h
@@ -83,24 +83,41 @@ class Repatcher : public JSC::RepatchBuf
          *                  blx     r8
          *
          * ARM has to run stub calls through a veneer in order for THROW to
          * work properly. The address that must be patched is the load into
          * 'ip', not the load into 'r8'.
          */
         CheckIsStubCall(call.labelAtOffset(0));
         JSC::RepatchBuffer::relink(call.callAtOffset(-4), stub);
+#elif defined JS_CPU_MIPS
+        /*
+         * Stub calls on MIPS look like this:
+         *
+         *                  lui     v0, hi(stub)
+         *                  ori     v0, v0, lo(stub)
+         *                  lui     t9, hi(JaegerStubVeneer)
+         *                  ori     t9, t9, lo(JaegerStubVeneer)
+         *                  jalr    t9
+         *                  nop
+         * call label ->    xxx
+         *
+         * MIPS has to run stub calls through a veneer in order for THROW to
+         * work properly. The address that must be patched is the load into
+         * 'v0', not the load into 't9'.
+         */
+        JSC::RepatchBuffer::relink(call.callAtOffset(-8), stub);
 #else
 # error
 #endif
     }
 
     /* Patch the offset of a Value load emitted by loadValueWithAddressOffsetPatch. */
     void patchAddressOffsetForValueLoad(CodeLocationLabel label, uint32_t offset) {
-#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC
+#if defined JS_CPU_X64 || defined JS_CPU_ARM || defined JS_CPU_SPARC || defined JS_CPU_MIPS 
         repatch(label.dataLabel32AtOffset(0), offset);
 #elif defined JS_CPU_X86
         static const unsigned LOAD_TYPE_OFFSET = 6;
         static const unsigned LOAD_DATA_OFFSET = 12;
 
         /*
          * We have the following sequence to patch:
          *
@@ -110,17 +127,17 @@ class Repatcher : public JSC::RepatchBuf
         repatch(label.dataLabel32AtOffset(LOAD_DATA_OFFSET), offset);
         repatch(label.dataLabel32AtOffset(LOAD_TYPE_OFFSET), offset + 4);
 #else
 # error
 #endif
     }
 
     void patchAddressOffsetForValueStore(CodeLocationLabel label, uint32_t offset, bool typeConst) {
-#if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC
+#if defined JS_CPU_ARM || defined JS_CPU_X64 || defined JS_CPU_SPARC || defined JS_CPU_MIPS
         (void) typeConst;
         repatch(label.dataLabel32AtOffset(0), offset);
 #elif defined JS_CPU_X86
         static const unsigned STORE_TYPE_OFFSET = 6;
         static const unsigned STORE_DATA_CONST_TYPE_OFFSET = 16;
         static const unsigned STORE_DATA_TYPE_OFFSET = 12;
 
         /*
--- a/js/src/methodjit/MachineRegs.h
+++ b/js/src/methodjit/MachineRegs.h
@@ -117,16 +117,18 @@ struct Registers {
 #if defined(JS_CPU_X86)
     static const RegisterID JSFrameReg = JSC::X86Registers::ebp;
 #elif defined(JS_CPU_X64)
     static const RegisterID JSFrameReg = JSC::X86Registers::ebx;
 #elif defined(JS_CPU_ARM)
     static const RegisterID JSFrameReg = JSC::ARMRegisters::r10;
 #elif defined(JS_CPU_SPARC)
     static const RegisterID JSFrameReg = JSC::SparcRegisters::l0;
+#elif defined(JS_CPU_MIPS)
+    static const RegisterID JSFrameReg = JSC::MIPSRegisters::s0;
 #endif
 
 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
     static const RegisterID ReturnReg = JSC::X86Registers::eax;
 # if defined(JS_CPU_X86) || defined(_WIN64)
     static const RegisterID ArgReg0 = JSC::X86Registers::ecx;
     static const RegisterID ArgReg1 = JSC::X86Registers::edx;
 #  if defined(JS_CPU_X64)
@@ -147,16 +149,22 @@ struct Registers {
 #elif JS_CPU_SPARC
     static const RegisterID ReturnReg = JSC::SparcRegisters::o0;
     static const RegisterID ArgReg0 = JSC::SparcRegisters::o0;
     static const RegisterID ArgReg1 = JSC::SparcRegisters::o1;
     static const RegisterID ArgReg2 = JSC::SparcRegisters::o2;
     static const RegisterID ArgReg3 = JSC::SparcRegisters::o3;
     static const RegisterID ArgReg4 = JSC::SparcRegisters::o4;
     static const RegisterID ArgReg5 = JSC::SparcRegisters::o5;
+#elif JS_CPU_MIPS
+    static const RegisterID ReturnReg = JSC::MIPSRegisters::v0;
+    static const RegisterID ArgReg0 = JSC::MIPSRegisters::a0;
+    static const RegisterID ArgReg1 = JSC::MIPSRegisters::a1;
+    static const RegisterID ArgReg2 = JSC::MIPSRegisters::a2;
+    static const RegisterID ArgReg3 = JSC::MIPSRegisters::a3;
 #endif
 
     static const RegisterID StackPointer = JSC::MacroAssembler::stackPointerRegister;
 
     static inline uint32_t maskReg(RegisterID reg) {
         return (1 << reg);
     }
 
@@ -248,16 +256,43 @@ struct Registers {
           (1 << JSC::SparcRegisters::l2)
         | (1 << JSC::SparcRegisters::l3)
         | (1 << JSC::SparcRegisters::l4)
         | (1 << JSC::SparcRegisters::l5)
         | (1 << JSC::SparcRegisters::l6)
         | (1 << JSC::SparcRegisters::l7);
 
     static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
+#elif defined(JS_CPU_MIPS)
+    static const uint32_t TempRegs =
+          (1 << JSC::MIPSRegisters::at)
+        | (1 << JSC::MIPSRegisters::v0)
+        | (1 << JSC::MIPSRegisters::v1)
+        | (1 << JSC::MIPSRegisters::a0)
+        | (1 << JSC::MIPSRegisters::a1)
+        | (1 << JSC::MIPSRegisters::a2)
+        | (1 << JSC::MIPSRegisters::a3)
+        | (1 << JSC::MIPSRegisters::t5)
+        | (1 << JSC::MIPSRegisters::t6)
+        | (1 << JSC::MIPSRegisters::t7);
+    /* t0-t4,t9 is reserved as a scratch register for the assembler.
+       We don't use t8 ($24), as we limit ourselves within $0 to $23 to
+       leave the bitmask for 8 FP registers. */
+
+    static const uint32_t SavedRegs =
+          (1 << JSC::MIPSRegisters::s1)
+        | (1 << JSC::MIPSRegisters::s2)
+        | (1 << JSC::MIPSRegisters::s3)
+        | (1 << JSC::MIPSRegisters::s4)
+        | (1 << JSC::MIPSRegisters::s5)
+        | (1 << JSC::MIPSRegisters::s6)
+        | (1 << JSC::MIPSRegisters::s7);
+    // s0 is reserved for JSFrameReg.
+
+    static const uint32_t SingleByteRegs = TempRegs | SavedRegs;
 #else
 # error "Unsupported platform"
 #endif
 
     static const uint32_t AvailRegs = SavedRegs | TempRegs;
 
     static bool isAvail(RegisterID reg) {
         uint32_t mask = maskReg(reg);
@@ -282,16 +317,18 @@ struct Registers {
         return 4;
 # else
         return 6;
 # endif
 #elif defined(JS_CPU_ARM)
         return 4;
 #elif defined(JS_CPU_SPARC)
         return 6;
+#elif defined(JS_CPU_MIPS)
+        return 4;
 #endif
     }
 
     static inline bool regForArg(CallConvention conv, uint32_t i, RegisterID *reg) {
 #if defined(JS_CPU_X86)
         static const RegisterID regs[] = {
             JSC::X86Registers::ecx,
             JSC::X86Registers::edx
@@ -332,16 +369,23 @@ struct Registers {
         static const RegisterID regs[] = {
             JSC::SparcRegisters::o0,
             JSC::SparcRegisters::o1,
             JSC::SparcRegisters::o2,
             JSC::SparcRegisters::o3,
             JSC::SparcRegisters::o4,
             JSC::SparcRegisters::o5
         };
+#elif defined(JS_CPU_MIPS)
+        static const RegisterID regs[] = {
+            JSC::MIPSRegisters::a0,
+            JSC::MIPSRegisters::a1,
+            JSC::MIPSRegisters::a2,
+            JSC::MIPSRegisters::a3,
+        };
 #endif
         JS_ASSERT(numArgRegs(conv) == mozilla::ArrayLength(regs));
         if (i > mozilla::ArrayLength(regs))
             return false;
         *reg = regs[i];
         return true;
     }
 
@@ -381,27 +425,42 @@ struct Registers {
     static const uint32_t TotalFPRegisters = 8;
     static const uint32_t TempFPRegs = (uint32_t)(
           (1 << JSC::SparcRegisters::f0)
         | (1 << JSC::SparcRegisters::f2)
         | (1 << JSC::SparcRegisters::f4)
         | (1 << JSC::SparcRegisters::f6)
         ) << TotalRegisters;
     static const FPRegisterID FPConversionTemp = JSC::SparcRegisters::f8;
+#elif defined(JS_CPU_MIPS)
+    /* TotalRegisters is 24, so TotalFPRegisters can be 8 to have a 32-bit
+       bit mask.
+       Note that the O32 ABI can access only even FP registers. */
+    static const uint32_t TotalFPRegisters = 8;
+    static const uint32_t TempFPRegs = (uint32_t)(
+          (1 << JSC::MIPSRegisters::f0)
+        | (1 << JSC::MIPSRegisters::f2)
+        | (1 << JSC::MIPSRegisters::f4)
+        | (1 << JSC::MIPSRegisters::f6)
+        ) << TotalRegisters;
+    // f16 is reserved as a scratch register for the assembler.
+    static const FPRegisterID FPConversionTemp = JSC::MIPSRegisters::f18;
 #else
 # error "Unsupported platform"
 #endif
 
     /* Temp reg that can be clobbered when setting up a fallible fast or ABI call. */
 #if defined(JS_CPU_X86) || defined(JS_CPU_X64)
     static const RegisterID ClobberInCall = JSC::X86Registers::ecx;
 #elif defined(JS_CPU_ARM)
     static const RegisterID ClobberInCall = JSC::ARMRegisters::r2;
 #elif defined(JS_CPU_SPARC)
     static const RegisterID ClobberInCall = JSC::SparcRegisters::l1;
+#elif defined(JS_CPU_MIPS)
+    static const RegisterID ClobberInCall = JSC::MIPSRegisters::at;
 #endif
 
     static const uint32_t AvailFPRegs = TempFPRegs;
 
     static inline uint32_t maskReg(FPRegisterID reg) {
         return (1 << reg) << TotalRegisters;
     }
 
--- a/js/src/methodjit/MethodJIT.cpp
+++ b/js/src/methodjit/MethodJIT.cpp
@@ -248,17 +248,17 @@ JS_STATIC_ASSERT(offsetof(FrameRegs, sp)
  * We make sure our CFI covers the code address GDB will actually use, by
  * placing a 'nop' *before* the entry point --- it is never executed --- and
  * having our CFI apply starting at that nop.
  */
 
 #if defined(__GNUC__) && !defined(_WIN64)
 
 /* If this assert fails, you need to realign VMFrame to 16 bytes. */
-#ifdef JS_CPU_ARM
+#if defined(JS_CPU_ARM) || defined(JS_CPU_MIPS)
 JS_STATIC_ASSERT(sizeof(VMFrame) % 8 == 0);
 #else
 JS_STATIC_ASSERT(sizeof(VMFrame) % 16 == 0);
 #endif
 
 # if defined(JS_CPU_X64)
 
 /*
@@ -817,16 +817,17 @@ SYMBOL_STRING(JaegerStubVeneer) ":"     
      * The arguments are identical to those for js_* except that the target function should be in
      * 'ip'. */
 "   push    {ip,lr}"                        "\n"
 "   blx     ip"                             "\n"
 "   pop     {ip,pc}"                        "\n"
 );
 
 # elif defined(JS_CPU_SPARC)
+# elif defined(JS_CPU_MIPS)
 # else
 #  error "Unsupported CPU!"
 # endif
 #elif defined(_MSC_VER) && defined(JS_CPU_X86)
 
 /*
  *    *** DANGER ***
  * If these assertions break, update the constants below. The throwpoline
--- a/js/src/methodjit/MethodJIT.h
+++ b/js/src/methodjit/MethodJIT.h
@@ -47,17 +47,18 @@
 #include "jscompartment.h"
 
 #include "assembler/assembler/MacroAssemblerCodeRef.h"
 #include "assembler/assembler/CodeLocation.h"
 
 #if !defined JS_CPU_X64 && \
     !defined JS_CPU_X86 && \
     !defined JS_CPU_SPARC && \
-    !defined JS_CPU_ARM
+    !defined JS_CPU_ARM && \
+    !defined JS_CPU_MIPS
 # error "Oh no, you should define a platform so this compiles."
 #endif
 
 #if !defined(JS_NUNBOX32) && !defined(JS_PUNBOX64)
 # error "No boxing format selected."
 #endif
 
 namespace js {
@@ -92,16 +93,23 @@ struct VMFrame
     void *outgoing_p3;
     void *outgoing_p4;
     void *outgoing_p5;
 
     void *outgoing_p6;
 
     void *reserve_0;
     void *reserve_1;
+
+#elif defined(JS_CPU_MIPS)
+    /* Reserved 16 bytes for a0-a3 space in MIPS O32 ABI */
+    void         *unused0;
+    void         *unused1;
+    void         *unused2;
+    void         *unused3;
 #endif
 
     union Arguments {
         struct {
             void *ptr;
             void *ptr2;
         } x;
         struct {
@@ -199,16 +207,32 @@ struct VMFrame
     }
 #elif defined(JS_CPU_SPARC)
     JSStackFrame *topRetrunAddr;
     void* veneerReturn;
     void* _align;
     inline void** returnAddressLocation() {
         return reinterpret_cast<void**>(&this->veneerReturn);
     }
+#elif defined(JS_CPU_MIPS)
+    void *savedS0;
+    void *savedS1;
+    void *savedS2;
+    void *savedS3;
+    void *savedS4;
+    void *savedS5;
+    void *savedS6;
+    void *savedS7;
+    void *savedGP;
+    void *savedRA;
+    void *unused4;  // For alignment.
+
+    inline void** returnAddressLocation() {
+        return reinterpret_cast<void**>(this) - 1;
+    }
 #else
 # error "The VMFrame layout isn't defined for your processor architecture!"
 #endif
 
     JSRuntime *runtime() { return cx->runtime; }
 
     /*
      * Get the current frame and JIT. Note that these are NOT stable in case
@@ -221,28 +245,31 @@ struct VMFrame
 
     /* Get the inner script/PC in case of inlining. */
     inline JSScript *script();
     inline jsbytecode *pc();
 
 #if defined(JS_CPU_SPARC)
     static const size_t offsetOfFp = 30 * sizeof(void *) + FrameRegs::offsetOfFp;
     static const size_t offsetOfInlined = 30 * sizeof(void *) + FrameRegs::offsetOfInlined;
+#elif defined(JS_CPU_MIPS)
+    static const size_t offsetOfFp = 8 * sizeof(void *) + FrameRegs::offsetOfFp;
+    static const size_t offsetOfInlined = 8 * sizeof(void *) + FrameRegs::offsetOfInlined;
 #else
     static const size_t offsetOfFp = 4 * sizeof(void *) + FrameRegs::offsetOfFp;
     static const size_t offsetOfInlined = 4 * sizeof(void *) + FrameRegs::offsetOfInlined;
 #endif
 
     static void staticAssert() {
         JS_STATIC_ASSERT(offsetOfFp == offsetof(VMFrame, regs) + FrameRegs::offsetOfFp);
         JS_STATIC_ASSERT(offsetOfInlined == offsetof(VMFrame, regs) + FrameRegs::offsetOfInlined);
     }
 };
 
-#if defined(JS_CPU_ARM) || defined(JS_CPU_SPARC)
+#if defined(JS_CPU_ARM) || defined(JS_CPU_SPARC) || defined(JS_CPU_MIPS)
 // WARNING: Do not call this function directly from C(++) code because it is not ABI-compliant.
 extern "C" void JaegerStubVeneer(void);
 #endif
 
 namespace mjit {
 
 /*
  * For a C++ or scripted call made from JIT code, indicates properties of the
--- a/js/src/methodjit/NunboxAssembler.h
+++ b/js/src/methodjit/NunboxAssembler.h
@@ -202,16 +202,22 @@ class NunboxAssembler : public JSC::Macr
         /* 
          * On ARM, the first instruction loads the offset from a literal pool, so the label
          * returned points at that instruction.
          */
         DataLabel32 load = load64WithAddressOffsetPatch(address, treg, dreg);
         JS_ASSERT(differenceBetween(start, load) == 0);
         (void) load;
         return start;
+#elif defined JS_CPU_MIPS
+        /*
+         * On MIPS there are LUI/ORI to patch.
+         */
+        load64WithPatch(address, treg, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
+        return start;
 #endif
     }
 
     /*
      * Store a (64b) js::Value from type |treg| and payload |dreg| into |address|, and
      * return a label which can be used by
      * ICRepatcher::patchAddressOffsetForValueStore to patch the address'
      * offset.
@@ -227,32 +233,44 @@ class NunboxAssembler : public JSC::Macr
         DBGLABEL_NOMASM(endType);
         storePayload(dreg, address);
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 6);
         JS_ASSERT(differenceBetween(endType, endPayload) == 6);
         return start;
 #elif defined JS_CPU_ARM || defined JS_CPU_SPARC
         return store64WithAddressOffsetPatch(treg, dreg, address);
+#elif defined JS_CPU_MIPS
+        /*
+         * On MIPS there are LUI/ORI to patch.
+         */
+        store64WithPatch(address, treg, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
+        return start;
 #endif
     }
 
     /* Overloaded for storing a constant type. */
     DataLabel32 storeValueWithAddressOffsetPatch(ImmType type, RegisterID dreg, Address address) {
         DataLabel32 start = dataLabel32();
 #if defined JS_CPU_X86
         storeTypeTag(type, address);
         DBGLABEL_NOMASM(endType);
         storePayload(dreg, address);
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 10);
         JS_ASSERT(differenceBetween(endType, endPayload) == 6);
         return start;
 #elif defined JS_CPU_ARM || defined JS_CPU_SPARC
         return store64WithAddressOffsetPatch(type, dreg, address);
+#elif defined JS_CPU_MIPS
+        /*
+         * On MIPS there are LUI/ORI to patch.
+         */
+        store64WithPatch(address, type, dreg, TAG_OFFSET, PAYLOAD_OFFSET);
+        return start;
 #endif
     }
 
     /* Overloaded for storing constant type and data. */
     DataLabel32 storeValueWithAddressOffsetPatch(const Value &v, Address address) {
         jsval_layout jv = JSVAL_TO_IMPL(v);
         ImmTag type(jv.s.tag);
         Imm32 payload(jv.s.payload.u32);
@@ -262,16 +280,22 @@ class NunboxAssembler : public JSC::Macr
         DBGLABEL_NOMASM(endType);
         store32(payload, payloadOf(address));
         DBGLABEL_NOMASM(endPayload);
         JS_ASSERT(differenceBetween(start, endType) == 10);
         JS_ASSERT(differenceBetween(endType, endPayload) == 10);
         return start;
 #elif defined JS_CPU_ARM || defined JS_CPU_SPARC
         return store64WithAddressOffsetPatch(type, payload, address);
+#elif defined JS_CPU_MIPS
+        /*
+         * On MIPS there are LUI/ORI to patch.
+         */
+        store64WithPatch(address, type, payload, TAG_OFFSET, PAYLOAD_OFFSET);
+        return start;
 #endif
     }
 
     /* Overloaded for store with value remat info. */
     DataLabel32 storeValueWithAddressOffsetPatch(const ValueRemat &vr, Address address) {
         JS_ASSERT(!vr.isFPRegister());
         if (vr.isConstant()) {
             return storeValueWithAddressOffsetPatch(vr.value(), address);
@@ -465,16 +489,22 @@ class NunboxAssembler : public JSC::Macr
         m_assembler.movd_rr(srcDest, dataReg);
         m_assembler.psrldq_rr(srcDest, 4);
         m_assembler.movd_rr(srcDest, typeReg);
 #elif defined JS_CPU_SPARC
         breakDoubleTo32(srcDest, typeReg, dataReg);
 #elif defined JS_CPU_ARM
         // Yes, we are backwards from SPARC.
         fastStoreDouble(srcDest, dataReg, typeReg);
+#elif defined JS_CPU_MIPS
+#if defined(IS_LITTLE_ENDIAN)
+        fastStoreDouble(srcDest, dataReg, typeReg);
+#else
+        fastStoreDouble(srcDest, typeReg, dataReg);
+#endif
 #else
         JS_NOT_REACHED("implement this - push double, pop pop is easiest");
 #endif
     }
 
     void loadStaticDouble(const double *dp, FPRegisterID dest, RegisterID scratch) {
         move(ImmPtr(dp), scratch);
         loadDouble(Address(scratch), dest);
new file mode 100644
--- /dev/null
+++ b/js/src/methodjit/TrampolineMIPS.cpp
@@ -0,0 +1,344 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=4 sw=4 et tw=99:
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Jaegermonkey.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ *
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Chao-ying Fu <fu@mips.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "jstypes.h"
+
+/*
+ * The MIPS VMFrame is 112 bytes as follows.
+ *
+ * 108  [ unused4      ] For alignment.
+ * 104  [ ra           ] 
+ * 100  [ gp           ] If PIC code is generated, we will save gp.
+ *  96  [ s7           ] 
+ *  92  [ s6           ] 
+ *  88  [ s5           ] 
+ *  84  [ s4           ] 
+ *  80  [ s3           ] 
+ *  76  [ s2           ] 
+ *  72  [ s1           ] 
+ *  68  [ s0           ] 
+ *  64  [ stubRejoin   ] 
+ *  60  [ entrycode    ] 
+ *  56  [ entryfp      ]
+ *  52  [ stkLimit     ]
+ *  48  [ cx           ]
+ *  44  [ regs.fp_     ]
+ *  40  [ regs.inlined_]
+ *  36  [ regs.pc      ]
+ *  32  [ regs.sp      ]
+ *  28  [ scratch      ]
+ *  24  [ previous     ]
+ *  20  [ args.ptr2    ]  [ dynamicArgc ]  (union)
+ *  16  [ args.ptr     ]  [ lazyArgsObj ]  (union)
+ *  12  [ unused3      ] O32 ABI, space for a3 (used in callee)
+ *   8  [ unused2      ] O32 ABI, space for a2 (used in callee)
+ *   4  [ unused1      ] O32 ABI, space for a1 (used in callee)
+ *   0  [ unused0      ] O32 ABI, space for a0 (used in callee)
+ */
+
+asm (
+    ".text"     "\n"
+    ".align 2"  "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerThrowpoline"  "\n"
+    ".ent   JaegerThrowpoline"  "\n"
+    ".type  JaegerThrowpoline,@function"    "\n"
+"JaegerThrowpoline:"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+    "la     $25,js_InternalThrow"   "\n"
+    ".reloc 1f,R_MIPS_JALR,js_InternalThrow"    "\n"
+"1: jalr    $25"    "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#else
+    "jal    js_InternalThrow"       "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#endif
+    "beq    $2,$0,1f"   "\n"
+    "nop"   "\n"
+    "jr     $2  # jump to a scripted handler"   "\n"
+    "nop"   "\n"
+"1:"        "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+    "la     $25,PopActiveVMFrame"   "\n"
+    ".reloc 1f,R_MIPS_JALR,PopActiveVMFrame"    "\n"
+"1:  jalr   $25"    "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#else
+    "jal    PopActiveVMFrame"       "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#endif
+    "lw     $31,104($29)"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+#endif
+    "lw     $23,96($29)"    "\n"
+    "lw     $22,92($29)"    "\n"
+    "lw     $21,88($29)"    "\n"
+    "lw     $20,84($29)"    "\n"
+    "lw     $19,80($29)"    "\n"
+    "lw     $18,76($29)"    "\n"
+    "lw     $17,72($29)"    "\n"
+    "lw     $16,68($29)"    "\n"
+    "li     $2,0    # return 0 to represent an unhandled exception."    "\n"
+    "jr     $31"            "\n"
+    "addiu  $29,$29,112"    "\n"
+    ".set   reorder"        "\n"
+    ".set   macro"          "\n"
+    ".end   JaegerThrowpoline" "\n"
+    ".size  JaegerThrowpoline,.-JaegerThrowpoline"  "\n"
+);
+
+asm (
+    ".text"     "\n"
+    ".align 2"  "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerTrampoline"   "\n"
+    ".ent   JaegerTrampoline"   "\n"
+    ".type  JaegerTrampoline,@function" "\n"
+"JaegerTrampoline:"     "\n"
+#if defined(__PIC__)
+    "lui    $28,%hi(_gp_disp)"  "\n"
+    "addiu  $28,$28,%lo(_gp_disp)"      "\n"
+    "addu   $28,$28,$25"    "\n"
+#endif
+    "addiu  $29,$29,-112"   "\n"
+    "sw     $31,104($29)"   "\n"
+#if defined(__PIC__)
+    "sw     $28,100($29)"   "\n"
+#endif
+    "sw     $23,96($29)"    "\n"
+    "sw     $22,92($29)"    "\n"
+    "sw     $21,88($29)"    "\n"
+    "sw     $20,84($29)"    "\n"
+    "sw     $19,80($29)"    "\n"
+    "sw     $18,76($29)"    "\n"
+    "sw     $17,72($29)"    "\n"
+    "sw     $16,68($29)"    "\n"
+    "sw     $0,64($29)  # stubRejoin"	"\n"
+    "sw     $5,60($29)  # entrycode"	"\n"
+    "sw     $5,56($29)  # entryfp"	"\n"
+    "sw     $7,52($29)  # stackLimit"	"\n"
+    "sw     $4,48($29)  # cx"	"\n"
+    "sw     $5,44($29)  # regs.fp"	"\n"
+    "move   $16,$5      # preserve fp to s0"    "\n"
+    "move   $17,$6      # preserve code to s1"  "\n"
+#if defined(__PIC__)
+    "la     $25,PushActiveVMFrame"  "\n"
+    ".reloc 1f,R_MIPS_JALR,PushActiveVMFrame"   "\n"
+"1:  jalr    $25"    "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#else
+    "jal    PushActiveVMFrame"      "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#endif
+
+    "move   $25,$17 # move code to $25"	"\n"
+    "jr     $25     # jump to the compiled JavaScript Function"	"\n"
+    "nop"       "\n"
+    ".set   reorder"    "\n"
+    ".set   macro"      "\n"
+    ".end   JaegerTrampoline"   "\n"
+    ".size  JaegerTrampoline,.-JaegerTrampoline"    "\n"
+);
+
+asm (
+    ".text"     "\n"
+    ".align 2"  "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerTrampolineReturn" "\n"
+    ".ent   JaegerTrampolineReturn" "\n"
+    ".type  JaegerTrampolineReturn,@function"   "\n"
+"JaegerTrampolineReturn:"   "\n"
+#if defined(IS_LITTLE_ENDIAN)
+    "sw     $4,28($16)  # a0: fp->rval type for LITTLE-ENDIAN"  "\n"
+    "sw     $6,24($16)  # a2: fp->rval data for LITTLE-ENDIAN"  "\n"
+#else
+    "sw     $4,24($16)  # a0: fp->rval type for BIG-ENDIAN"     "\n"
+    "sw     $6,28($16)  # a2: fp->rval data for BIG-ENDIAN"     "\n"
+#endif
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+    "la     $25,PopActiveVMFrame"   "\n"
+    ".reloc 1f,R_MIPS_JALR,PopActiveVMFrame"    "\n"
+"1:  jalr    $25"    "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#else
+    "jal    PopActiveVMFrame"       "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#endif
+    "lw     $31,104($29)"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+#endif
+    "lw     $23,96($29)"    "\n"
+    "lw     $22,92($29)"    "\n"
+    "lw     $21,88($29)"    "\n"
+    "lw     $20,84($29)"    "\n"
+    "lw     $19,80($29)"    "\n"
+    "lw     $18,76($29)"    "\n"
+    "lw     $17,72($29)"    "\n"
+    "lw     $16,68($29)"    "\n"
+    "li     $2,1    # return ture to indicate successful completion"    "\n"
+    "jr     $31"    "\n"
+    "addiu  $29,$29,112"    "\n"
+    ".set   reorder"        "\n"
+    ".set   macro"          "\n"
+    ".end   JaegerTrampolineReturn" "\n"
+    ".size  JaegerTrampolineReturn,.-JaegerTrampolineReturn"    "\n"
+);
+
+asm (
+    ".text"     "\n"
+    ".align 2" "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerStubVeneer"   "\n"
+    ".ent   JaegerStubVeneer"   "\n"
+    ".type  JaegerStubVeneer,@function" "\n"
+"JaegerStubVeneer:"     "\n"
+    "addiu  $29,$29,-24 # Need 16 (a0-a3) + 4 (align) + 4 ($31) bytes"  "\n"
+    "sw     $31,20($29) # Store $31 to 20($29)" "\n"
+    "move   $25,$2      # the target address is passed from $2"  "\n"
+    "jalr   $25"    "\n"
+    "nop"           "\n"
+    "lw     $31,20($29)"        "\n"
+    "jr     $31"    "\n"
+    "addiu  $29,$29,24"         "\n"
+    ".set   reorder"    "\n"
+    ".set   macro"      "\n"
+    ".end   JaegerStubVeneer"   "\n"
+    ".size  JaegerStubVeneer,.-JaegerStubVeneer"    "\n"
+);
+
+asm (
+    ".text"     "\n"
+    ".align 2" "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerInterpolineScripted"	"\n"
+    ".ent   JaegerInterpolineScripted"	"\n"
+    ".type  JaegerInterpolineScripted,@function"    "\n"
+"JaegerInterpolineScripted:"	"\n"
+    "lw     $16,16($16) # Load f->prev_"  "\n"
+    "b      JaegerInterpoline"  "\n"
+    "sw     $16,44($29) # Update f->regs->fp_"  "\n"
+    ".set   reorder"    "\n"
+    ".set   macro"      "\n"
+    ".end   JaegerInterpolineScripted"   "\n"
+    ".size  JaegerInterpolineScripted,.-JaegerInterpolineScripted"  "\n"
+);
+
+asm (
+    ".text"     "\n"
+    ".align 2" "\n"
+    ".set   noreorder"  "\n"
+    ".set   nomacro"    "\n"
+    ".set   nomips16"   "\n"
+    ".globl JaegerInterpoline"	"\n"
+    ".ent   JaegerInterpoline"	"\n"
+    ".type  JaegerInterpoline,@function"    "\n"
+"JaegerInterpoline:"	"\n"
+    "move   $5,$4   # returntype"   "\n"
+    "move   $4,$6   # returnData"   "\n"
+    "move   $6,$2   # returnReg"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+    "la     $25,js_InternalInterpret"   "\n"
+    ".reloc 1f,R_MIPS_JALR,js_InternalInterpret"    "\n"
+"1:  jalr    $25"    "\n"
+    "move   $7,$29  # f"    "\n"
+#else
+    "jal    js_InternalInterpret"   "\n"
+    "move   $7,$29  # f"    "\n"
+#endif
+    "lw     $16,44($29) # Load f->regs->fp_ to s0"  "\n"
+#if defined(IS_LITTLE_ENDIAN)
+    "lw     $4,28($16)  # a0: fp->rval type for LITTLE-ENDIAN"  "\n"
+    "lw     $6,24($16)  # a2: fp->rval data for LITTLE-ENDIAN"  "\n"
+#else
+    "lw     $4,24($16)  # a0: fp->rval type for BIG-ENDIAN"     "\n"
+    "lw     $6,28($16)  # a2: fp->rval data for BIG-ENDIAN"     "\n"
+#endif
+    "lw     $5,28($29)  # Load sctrach -> argc"     "\n"
+    "beq    $2,$0,1f"   "\n"
+    "nop"               "\n"
+    "jr     $2"         "\n"
+    "nop"               "\n"
+"1:"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+    "la     $25,PopActiveVMFrame"   "\n"
+    ".reloc 1f,R_MIPS_JALR,PopActiveVMFrame"    "\n"
+"1:  jalr   $25"    "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#else
+    "jal    PopActiveVMFrame"       "\n"
+    "move   $4,$29  # set up a0"    "\n"
+#endif
+    "lw     $31,104($29)"    "\n"
+#if defined(__PIC__)
+    "lw     $28,100($29)"    "\n"
+#endif
+    "lw     $23,96($29)"    "\n"
+    "lw     $22,92($29)"    "\n"
+    "lw     $21,88($29)"    "\n"
+    "lw     $20,84($29)"    "\n"
+    "lw     $19,80($29)"    "\n"
+    "lw     $18,76($29)"    "\n"
+    "lw     $17,72($29)"    "\n"
+    "lw     $16,68($29)"    "\n"
+    "li     $2,0    # return 0"     "\n"
+    "jr     $31"    "\n"
+    "addiu  $29,$29,112"    "\n"
+    ".set   reorder"    "\n"
+    ".set   macro"      "\n"
+    ".end   JaegerInterpoline"	"\n"
+    ".size  JaegerInterpoline,.-JaegerInterpoline"  "\n"
+);
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -568,19 +568,18 @@ public class GeckoAppShell
         getMainHandler().post(new Runnable() { 
                 public void run() {
                     LayerView v = GeckoApp.mAppContext.getLayerController().getView();
 
                     LocationManager lm = (LocationManager)
                         GeckoApp.mAppContext.getSystemService(Context.LOCATION_SERVICE);
 
                     if (enable) {
-                        Criteria crit = new Criteria();
-                        crit.setAccuracy(Criteria.ACCURACY_FINE);
-                        String provider = lm.getBestProvider(crit, true);
+                        Criteria criteria = new Criteria();
+                        String provider = lm.getBestProvider(criteria, true);
                         if (provider == null)
                             return;
 
                         Looper l = Looper.getMainLooper();
                         Location loc = lm.getLastKnownLocation(provider);
                         if (loc != null) {
                             GeckoApp.mAppContext.onLocationChanged(loc);
                         }
--- a/toolkit/components/telemetry/Telemetry.cpp
+++ b/toolkit/components/telemetry/Telemetry.cpp
@@ -70,38 +70,33 @@ public:
   ~TelemetryImpl();
   
   static bool CanRecord();
   static already_AddRefed<nsITelemetry> CreateTelemetryInstance();
   static void ShutdownTelemetry();
   static void RecordSlowStatement(const nsACString &statement,
                                   const nsACString &dbName,
                                   PRUint32 delay);
-  static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
   struct StmtStats {
     PRUint32 hitCount;
     PRUint32 totalTime;
   };
   typedef nsBaseHashtableET<nsCStringHashKey, StmtStats> SlowSQLEntryType;
 
 private:
   bool AddSQLInfo(JSContext *cx, JSObject *rootObj, bool mainThread);
 
   // Like GetHistogramById, but returns the underlying C++ object, not the JS one.
   nsresult GetHistogramByName(const nsACString &name, Histogram **ret);
-  bool ShouldReflectHistogram(Histogram *h);
-  void IdentifyCorruptHistograms(StatisticsRecorder::Histograms &hs);
-  typedef StatisticsRecorder::Histograms::iterator HistogramIterator;
-  // This is used for speedy string->Telemetry::ID conversions
+  // This is used for speedy JS string->Telemetry::ID conversions
   typedef nsBaseHashtableET<nsCharPtrHashKey, Telemetry::ID> CharPtrEntryType;
   typedef nsTHashtable<CharPtrEntryType> HistogramMapType;
   HistogramMapType mHistogramMap;
   bool mCanRecord;
   static TelemetryImpl *sTelemetry;
-  static bool gCorruptHistograms[Telemetry::HistogramCount];
   nsTHashtable<SlowSQLEntryType> mSlowSQLOnMainThread;
   nsTHashtable<SlowSQLEntryType> mSlowSQLOnOtherThread;
   nsTHashtable<nsCStringHashKey> mTrackedDBs;
   Mutex mHashMutex;
 };
 
 TelemetryImpl*  TelemetryImpl::sTelemetry = NULL;
 
@@ -215,54 +210,42 @@ FillRanges(JSContext *cx, JSObject *arra
 {
   for (size_t i = 0; i < h->bucket_count(); i++) {
     if (!JS_DefineElement(cx, array, i, INT_TO_JSVAL(h->ranges(i)), NULL, NULL, JSPROP_ENUMERATE))
       return false;
   }
   return true;
 }
 
-enum reflectStatus {
-  REFLECT_OK,
-  REFLECT_CORRUPT,
-  REFLECT_FAILURE
-};
-
-enum reflectStatus
+JSBool
 ReflectHistogramSnapshot(JSContext *cx, JSObject *obj, Histogram *h)
 {
   Histogram::SampleSet ss;
   h->SnapshotSample(&ss);
-
-  // We don't want to reflect corrupt histograms.
-  if (h->FindCorruption(ss) != Histogram::NO_INCONSISTENCIES) {
-    return REFLECT_CORRUPT;
-  }
-
   JSObject *counts_array;
   JSObject *rarray;
   const size_t count = h->bucket_count();
   if (!(JS_DefineProperty(cx, obj, "min", INT_TO_JSVAL(h->declared_min()), NULL, NULL, JSPROP_ENUMERATE)
         && JS_DefineProperty(cx, obj, "max", INT_TO_JSVAL(h->declared_max()), NULL, NULL, JSPROP_ENUMERATE)
         && JS_DefineProperty(cx, obj, "histogram_type", INT_TO_JSVAL(h->histogram_type()), NULL, NULL, JSPROP_ENUMERATE)
         && JS_DefineProperty(cx, obj, "sum", DOUBLE_TO_JSVAL(ss.sum()), NULL, NULL, JSPROP_ENUMERATE)
         && (rarray = JS_NewArrayObject(cx, count, NULL))
         && JS_DefineProperty(cx, obj, "ranges", OBJECT_TO_JSVAL(rarray), NULL, NULL, JSPROP_ENUMERATE)
         && FillRanges(cx, rarray, h)
         && (counts_array = JS_NewArrayObject(cx, count, NULL))
         && JS_DefineProperty(cx, obj, "counts", OBJECT_TO_JSVAL(counts_array), NULL, NULL, JSPROP_ENUMERATE)
         )) {
-    return REFLECT_FAILURE;
+    return JS_FALSE;
   }
   for (size_t i = 0; i < count; i++) {
     if (!JS_DefineElement(cx, counts_array, i, INT_TO_JSVAL(ss.counts(i)), NULL, NULL, JSPROP_ENUMERATE)) {
-      return REFLECT_FAILURE;
+      return JS_FALSE;
     }
   }
-  return REFLECT_OK;
+  return JS_TRUE;
 }
 
 JSBool
 JSHistogram_Add(JSContext *cx, uintN argc, jsval *vp)
 {
   if (!argc) {
     JS_ReportError(cx, "Expected one argument");
     return JS_FALSE;
@@ -302,30 +285,18 @@ JSHistogram_Snapshot(JSContext *cx, uint
   if (!obj) {
     return JS_FALSE;
   }
 
   Histogram *h = static_cast<Histogram*>(JS_GetPrivate(cx, obj));
   JSObject *snapshot = JS_NewObject(cx, NULL, NULL, NULL);
   if (!snapshot)
     return JS_FALSE;
-
-  switch (ReflectHistogramSnapshot(cx, snapshot, h)) {
-  case REFLECT_FAILURE:
-    return JS_FALSE;
-  case REFLECT_CORRUPT:
-    JS_ReportError(cx, "Histogram is corrupt");
-    return JS_FALSE;
-  case REFLECT_OK:
-    JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot));
-    return JS_TRUE;
-  default:
-    MOZ_NOT_REACHED("unhandled reflection status");
-    return JS_FALSE;
-  }
+  JS_SET_RVAL(cx, vp, OBJECT_TO_JSVAL(snapshot));
+  return ReflectHistogramSnapshot(cx, snapshot, h);
 }
 
 nsresult 
 WrapAndReturnHistogram(Histogram *h, JSContext *cx, jsval *ret)
 {
   static JSClass JSHistogram_class = {
     "JSHistogram",  /* name */
     JSCLASS_HAS_PRIVATE, /* flags */
@@ -436,55 +407,38 @@ TelemetryImpl::AddSQLInfo(JSContext *cx,
   PRUint32 num = sqlMap->EnumerateEntries(StatementEnumerator,
                                           static_cast<void*>(&args));
   if (num != sqlMap->Count())
     return false;
 
   return true;
 }
 
+
 nsresult
-TelemetryImpl::GetHistogramEnumId(const char *name, Telemetry::ID *id)
+TelemetryImpl::GetHistogramByName(const nsACString &name, Histogram **ret)
 {
-  if (!sTelemetry) {
-    return NS_ERROR_FAILURE;
-  }
-
   // Cache names
   // Note the histogram names are statically allocated
-  TelemetryImpl::HistogramMapType *map = &sTelemetry->mHistogramMap;
-  if (!map->Count()) {
+  if (!mHistogramMap.Count()) {
     for (PRUint32 i = 0; i < Telemetry::HistogramCount; i++) {
-      CharPtrEntryType *entry = map->PutEntry(gHistograms[i].id);
+      CharPtrEntryType *entry = mHistogramMap.PutEntry(gHistograms[i].id);
       if (NS_UNLIKELY(!entry)) {
-        map->Clear();
+        mHistogramMap.Clear();
         return NS_ERROR_OUT_OF_MEMORY;
       }
       entry->mData = (Telemetry::ID) i;
     }
   }
 
-  CharPtrEntryType *entry = map->GetEntry(name);
-  if (!entry) {
-    return NS_ERROR_INVALID_ARG;
-  }
-  *id = entry->mData;
-  return NS_OK;
-}
+  CharPtrEntryType *entry = mHistogramMap.GetEntry(PromiseFlatCString(name).get());
+  if (!entry)
+    return NS_ERROR_FAILURE;
 
-nsresult
-TelemetryImpl::GetHistogramByName(const nsACString &name, Histogram **ret)
-{
-  Telemetry::ID id;
-  nsresult rv = GetHistogramEnumId(PromiseFlatCString(name).get(), &id);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  rv = GetHistogramByEnumId(id, ret);
+  nsresult rv = GetHistogramByEnumId(entry->mData, ret);
   if (NS_FAILED(rv))
     return rv;
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::HistogramFrom(const nsACString &name, const nsACString &existing_name,
@@ -508,123 +462,35 @@ TelemetryImpl::HistogramFrom(const nsACS
     return rv;
 
   Histogram::SampleSet ss;
   existing->SnapshotSample(&ss);
   clone->AddSampleSet(ss);
   return WrapAndReturnHistogram(clone, cx, ret);
 }
 
-void
-TelemetryImpl::IdentifyCorruptHistograms(StatisticsRecorder::Histograms &hs)
-{
-  for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) {
-    Histogram *h = *it;
-
-    Telemetry::ID id;
-    nsresult rv = GetHistogramEnumId(h->histogram_name().c_str(), &id);
-    // This histogram isn't a static histogram, just ignore it.
-    if (NS_FAILED(rv)) {
-      continue;
-    }
-
-    if (gCorruptHistograms[id]) {
-      continue;
-    }
-
-    Histogram::SampleSet ss;
-    h->SnapshotSample(&ss);
-    Histogram::Inconsistencies check = h->FindCorruption(ss);
-    bool corrupt = (check != Histogram::NO_INCONSISTENCIES);
-
-    if (corrupt) {
-      Telemetry::ID corruptID = Telemetry::HistogramCount;
-      if (check & Histogram::RANGE_CHECKSUM_ERROR) {
-        corruptID = Telemetry::RANGE_CHECKSUM_ERRORS;
-      } else if (check & Histogram::BUCKET_ORDER_ERROR) {
-        corruptID = Telemetry::BUCKET_ORDER_ERRORS;
-      } else if (check & Histogram::COUNT_HIGH_ERROR) {
-        corruptID = Telemetry::TOTAL_COUNT_HIGH_ERRORS;
-      } else if (check & Histogram::COUNT_LOW_ERROR) {
-        corruptID = Telemetry::TOTAL_COUNT_LOW_ERRORS;
-      }
-      Telemetry::Accumulate(corruptID, 1);
-    }
-
-    gCorruptHistograms[id] = corrupt;
-  }
-}
-
-bool
-TelemetryImpl::ShouldReflectHistogram(Histogram *h)
-{
-  const char *name = h->histogram_name().c_str();
-  Telemetry::ID id;
-  nsresult rv = GetHistogramEnumId(name, &id);
-  if (NS_FAILED(rv)) {
-    // GetHistogramEnumId generally should not fail.  But a lookup
-    // failure shouldn't prevent us from reflecting histograms into JS.
-    //
-    // However, these two histograms are created by Histogram itself for
-    // tracking corruption.  We have our own histograms for that, so
-    // ignore these two.
-    if (strcmp(name, "Histogram.InconsistentCountHigh") == 0
-        || strcmp(name, "Histogram.InconsistentCountLow") == 0) {
-      return false;
-    }
-    return true;
-  } else {
-    return !gCorruptHistograms[id];
-  }
-}
-
 NS_IMETHODIMP
 TelemetryImpl::GetHistogramSnapshots(JSContext *cx, jsval *ret)
 {
   JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
   if (!root_obj)
     return NS_ERROR_FAILURE;
   *ret = OBJECT_TO_JSVAL(root_obj);
 
-  StatisticsRecorder::Histograms hs;
-  StatisticsRecorder::GetHistograms(&hs);
-
-  // We identify corrupt histograms first, rather than interspersing it
-  // in the loop below, to ensure that our corruption statistics don't
-  // depend on histogram enumeration order.
-  //
-  // Of course, we hope that all of these corruption-statistics
-  // histograms are not themselves corrupt...
-  IdentifyCorruptHistograms(hs);
-
-  // OK, now we can actually reflect things.
-  for (HistogramIterator it = hs.begin(); it != hs.end(); ++it) {
+  StatisticsRecorder::Histograms h;
+  StatisticsRecorder::GetHistograms(&h);
+  for (StatisticsRecorder::Histograms::iterator it = h.begin(); it != h.end();++it) {
     Histogram *h = *it;
-    if (!ShouldReflectHistogram(h)) {
-      continue;
-    }
-
     JSObject *hobj = JS_NewObject(cx, NULL, NULL, NULL);
-    if (!hobj) {
+    if (!(hobj
+          && JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(),
+                               OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE)
+          && ReflectHistogramSnapshot(cx, hobj, h))) {
       return NS_ERROR_FAILURE;
     }
-    switch (ReflectHistogramSnapshot(cx, hobj, h)) {
-    case REFLECT_CORRUPT:
-      // We can still hit this case even if ShouldReflectHistograms
-      // returns true.  The histogram lies outside of our control
-      // somehow; just skip it.
-      continue;
-    case REFLECT_FAILURE:
-      return NS_ERROR_FAILURE;
-    case REFLECT_OK:
-      if (!JS_DefineProperty(cx, root_obj, h->histogram_name().c_str(),
-                             OBJECT_TO_JSVAL(hobj), NULL, NULL, JSPROP_ENUMERATE)) {
-        return NS_ERROR_FAILURE;
-      }
-    }
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TelemetryImpl::GetSlowSQL(JSContext *cx, jsval *ret)
 {
   JSObject *root_obj = JS_NewObject(cx, NULL, NULL, NULL);
--- a/toolkit/components/telemetry/TelemetryHistograms.h
+++ b/toolkit/components/telemetry/TelemetryHistograms.h
@@ -336,17 +336,10 @@ HISTOGRAM(DOM_TIMERS_FIRED_PER_NATIVE_TI
 
 DOMSTORAGE_KEY_VAL_SIZE(GLOBAL, "global")
 DOMSTORAGE_KEY_VAL_SIZE(LOCAL, "local")
 DOMSTORAGE_KEY_VAL_SIZE(SESSION, "session")
 
 #undef DOMSTORAGE_KEY_VAL_SIZE
 #undef DOMSTORAGE_HISTOGRAM
 
-/**
- * Telemetry telemetry.
- */
-HISTOGRAM(RANGE_CHECKSUM_ERRORS, 1, 3000, 10, EXPONENTIAL, "Number of histograms with range checksum errors")
-HISTOGRAM(BUCKET_ORDER_ERRORS, 1, 3000, 10, EXPONENTIAL, "Number of histograms with bucket order errors")
-HISTOGRAM(TOTAL_COUNT_HIGH_ERRORS, 1, 3000, 10, EXPONENTIAL, "Number of histograms with total count high errors")
-HISTOGRAM(TOTAL_COUNT_LOW_ERRORS, 1, 3000, 10, EXPONENTIAL, "Number of histograms with total count low errors")
 
 #undef HISTOGRAM_BOOLEAN
--- a/toolkit/mozapps/downloads/DownloadTaskbarProgress.jsm
+++ b/toolkit/mozapps/downloads/DownloadTaskbarProgress.jsm
@@ -215,29 +215,31 @@ var DownloadTaskbarProgressUpdater =
   _totalTransferred: 0,
 
   /**
    * Update the active window's taskbar indicator with the current state. There
    * are two cases here:
    * 1. If the active window is the download window, then we always update
    *    the taskbar indicator.
    * 2. If the active window isn't the download window, then we update only if
-   *    the status is Normal, i.e. one or more downloads are currently
-   *    progressing. If we aren't, then we clear the indicator.
+   *    the status is normal or indeterminate. i.e. one or more downloads are
+   *    currently progressing or in scan mode. If we aren't, then we clear the
+   *    indicator.
    */
   _updateTaskbar: function DTPU_updateTaskbar()
   {
     if (!this._activeTaskbarProgress) {
       return;
     }
 
     // If the active window is not the download manager window, set the state
-    // only if it is Normal
+    // only if it is normal or indeterminate.
     if (this._activeWindowIsDownloadWindow ||
-        (this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL)) {
+        (this._taskbarState == Ci.nsITaskbarProgress.STATE_NORMAL ||
+         this._taskbarState == Ci.nsITaskbarProgress.STATE_INDETERMINATE)) {
       this._activeTaskbarProgress.setProgressState(this._taskbarState,
                                                    this._totalTransferred,
                                                    this._totalSize);
     }
     // Clear any state otherwise
     else {
       this._clearTaskbar();
     }
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3752,19 +3752,21 @@ void nsWindow::DispatchPendingEvents()
   // At the same time, we don't want to recurse through here
   // as that would prevent us from dispatching starved paints.
   static int recursionBlocker = 0;
   if (recursionBlocker++ == 0) {
     NS_ProcessPendingEvents(nsnull, PR_MillisecondsToInterval(100));
     --recursionBlocker;
   }
 
-  // Quickly check to see if there are any
-  // paint events pending.
-  if (::GetQueueStatus(QS_PAINT)) {
+  // Quickly check to see if there are any paint events pending,
+  // but only dispatch them if it has been long enough since the
+  // last paint completed.
+  if (::GetQueueStatus(QS_PAINT) &&
+      ((TimeStamp::Now() - mLastPaintEndTime).ToMilliseconds() >= 50)) {
     // Find the top level window.
     HWND topWnd = WinUtils::GetTopLevelHWND(mWnd);
 
     // Dispatch pending paints for topWnd and all its descendant windows.
     // Note: EnumChildWindows enumerates all descendant windows not just
     // the children (but not the window itself).
     nsWindow::DispatchStarvedPaints(topWnd, 0);
     ::EnumChildWindows(topWnd, nsWindow::DispatchStarvedPaints, 0);
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -56,16 +56,18 @@
 #include "nsIdleService.h"
 #include "nsToolkit.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "gfxWindowsSurface.h"
 #include "nsWindowDbg.h"
 #include "cairo.h"
 #include "nsITimer.h"
+#include "mozilla/TimeStamp.h"
+
 #ifdef CAIRO_HAS_D2D_SURFACE
 #include "gfxD2DSurface.h"
 #endif
 
 #include "nsWinGesture.h"
 
 #include "WindowHook.h"
 #include "TaskbarWindowPreview.h"
@@ -89,16 +91,18 @@ class nsIFile;
 class imgIContainer;
 
 /**
  * Native WIN32 window wrapper.
  */
 
 class nsWindow : public nsBaseWidget
 {
+  typedef mozilla::TimeStamp TimeStamp;
+  typedef mozilla::TimeDuration TimeDuration;
   typedef mozilla::widget::WindowHook WindowHook;
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
   typedef mozilla::widget::TaskbarWindowPreview TaskbarWindowPreview;
 #endif
 public:
   nsWindow();
   virtual ~nsWindow();
 
@@ -606,16 +610,20 @@ protected:
 #if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_WIN7
   // Weak ref to the nsITaskbarWindowPreview associated with this window
   nsWeakPtr             mTaskbarPreview;
   // True if the taskbar (possibly through the tab preview) tells us that the
   // icon has been created on the taskbar.
   bool                  mHasTaskbarIconBeenCreated;
 #endif
 
+  // The point in time at which the last paint completed. We use this to avoid
+  //  painting too rapidly in response to frequent input events.
+  TimeStamp mLastPaintEndTime;
+
 #ifdef ACCESSIBILITY
   static BOOL           sIsAccessibilityOn;
   static HINSTANCE      sAccLib;
   static LPFNLRESULTFROMOBJECT sLresultFromObject;
 #endif // ACCESSIBILITY
 
   // sRedirectedKeyDown is WM_KEYDOWN message or WM_SYSKEYDOWN message which
   // was reirected to SendInput() API by OnKeyDown().
--- a/widget/windows/nsWindowGfx.cpp
+++ b/widget/windows/nsWindowGfx.cpp
@@ -600,16 +600,17 @@ bool nsWindow::OnPaint(HDC aDC, PRUint32
     }
   }
 
   if (!aDC) {
     ::EndPaint(mWnd, &ps);
   }
 
   mPaintDC = nsnull;
+  mLastPaintEndTime = TimeStamp::Now();
 
 #if defined(WIDGET_DEBUG_OUTPUT)
   if (debug_WantPaintFlashing())
   {
     // Only flash paint events which have not ignored the paint message.
     // Those that ignore the paint message aren't painting anything so there
     // is only the overhead of the dispatching the paint event.
     if (nsEventStatus_eIgnore != eventStatus) {