]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/MacroAssemblerMIPS.h
JavaScriptCore-7600.1.4.11.8.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerMIPS.h
index 9cdfffc8bc7c9c5beeeeaf9a1539589074504e78..71b5fa9dff079eee39ceba8cd340e1e1c7f4a790 100644 (file)
@@ -29,8 +29,8 @@
 
 #if ENABLE(ASSEMBLER) && CPU(MIPS)
 
-#include "MIPSAssembler.h"
 #include "AbstractMacroAssembler.h"
+#include "MIPSAssembler.h"
 
 namespace JSC {
 
@@ -43,6 +43,11 @@ public:
     {
     }
 
+    static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
+    {
+        return value >= -2147483647 - 1 && value <= 2147483647;
+    }
+
     static const Scale ScalePtr = TimesFour;
 
     // For storing immediate number
@@ -75,6 +80,7 @@ public:
     enum ResultCondition {
         Overflow,
         Signed,
+        PositiveOrZero,
         Zero,
         NonZero
     };
@@ -95,6 +101,7 @@ public:
     };
 
     static const RegisterID stackPointerRegister = MIPSRegisters::sp;
+    static const RegisterID framePointerRegister = MIPSRegisters::fp;
     static const RegisterID returnAddressRegister = MIPSRegisters::ra;
 
     // Integer arithmetic operations:
@@ -109,6 +116,11 @@ public:
         m_assembler.addu(dest, dest, src);
     }
 
+    void add32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.addu(dest, op1, op2);
+    }
+
     void add32(TrustedImm32 imm, RegisterID dest)
     {
         add32(imm, dest, dest);
@@ -116,7 +128,7 @@ public:
 
     void add32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
-        if (!imm.m_isPointer && imm.m_value >= -32768 && imm.m_value <= 32767
+        if (imm.m_value >= -32768 && imm.m_value <= 32767
             && !m_fixedWidth) {
             /*
               addiu     dest, src, imm
@@ -132,6 +144,11 @@ public:
         }
     }
 
+    void add32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        add32(imm, src, dest);
+    }
+
     void add32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -143,15 +160,12 @@ public:
               sw        dataTemp, offset(base)
             */
             m_assembler.lw(dataTempRegister, address.base, address.offset);
-            if (!imm.m_isPointer
-                && imm.m_value >= -32768 && imm.m_value <= 32767
+            if (imm.m_value >= -32768 && imm.m_value <= 32767
                 && !m_fixedWidth)
-                m_assembler.addiu(dataTempRegister, dataTempRegister,
-                                  imm.m_value);
+                m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
             else {
                 move(imm, immTempRegister);
-                m_assembler.addu(dataTempRegister, dataTempRegister,
-                                 immTempRegister);
+                m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
             }
             m_assembler.sw(dataTempRegister, address.base, address.offset);
         } else {
@@ -168,12 +182,10 @@ public:
             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);
+                m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
             else {
                 move(imm, immTempRegister);
-                m_assembler.addu(dataTempRegister, dataTempRegister,
-                                 immTempRegister);
+                m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
             }
             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
         }
@@ -185,6 +197,12 @@ public:
         add32(dataTempRegister, dest);
     }
 
+    void add32(AbsoluteAddress src, RegisterID dest)
+    {
+        load32(src.m_ptr, dataTempRegister);
+        add32(dataTempRegister, dest);
+    }
+
     void add32(RegisterID src, Address dest)
     {
         if (dest.offset >= -32768 && dest.offset <= 32767 && !m_fixedWidth) {
@@ -217,33 +235,61 @@ public:
         /*
            li   addrTemp, address
            li   immTemp, imm
-           lw   dataTemp, 0(addrTemp)
-           addu dataTemp, dataTemp, immTemp
+           lw   cmpTemp, 0(addrTemp)
+           addu dataTemp, cmpTemp, immTemp
            sw   dataTemp, 0(addrTemp)
         */
         move(TrustedImmPtr(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);
+        m_assembler.lw(cmpTempRegister, addrTempRegister, 0);
+        if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth)
+            m_assembler.addiu(dataTempRegister, cmpTempRegister, imm.m_value);
         else {
             move(imm, immTempRegister);
-            m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
+            m_assembler.addu(dataTempRegister, cmpTempRegister, immTempRegister);
         }
         m_assembler.sw(dataTempRegister, addrTempRegister, 0);
     }
 
+    void add64(TrustedImm32 imm, AbsoluteAddress address)
+    {
+        /*
+            add32(imm, address)
+            sltu  immTemp, dataTemp, cmpTemp    # set carry-in bit
+            lw    dataTemp, 4(addrTemp)
+            addiu dataTemp, imm.m_value >> 31 ? -1 : 0
+            addu  dataTemp, dataTemp, immTemp
+            sw    dataTemp, 4(addrTemp)
+        */
+        add32(imm, address);
+        m_assembler.sltu(immTempRegister, dataTempRegister, cmpTempRegister);
+        m_assembler.lw(dataTempRegister, addrTempRegister, 4);
+        if (imm.m_value >> 31)
+            m_assembler.addiu(dataTempRegister, dataTempRegister, -1);
+        m_assembler.addu(dataTempRegister, dataTempRegister, immTempRegister);
+        m_assembler.sw(dataTempRegister, addrTempRegister, 4);
+    }
+
+    void and32(Address src, RegisterID dest)
+    {
+        load32(src, dataTempRegister);
+        and32(dataTempRegister, dest);
+    }
+
     void and32(RegisterID src, RegisterID dest)
     {
         m_assembler.andInsn(dest, dest, src);
     }
 
+    void and32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.andInsn(dest, op1, op2);
+    }
+
     void and32(TrustedImm32 imm, RegisterID dest)
     {
-        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+        if (!imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
-        else if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
-                 && !m_fixedWidth)
+        else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth)
             m_assembler.andi(dest, dest, imm.m_value);
         else {
             /*
@@ -255,9 +301,16 @@ public:
         }
     }
 
-    void lshift32(TrustedImm32 imm, RegisterID dest)
+    void and32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
-        m_assembler.sll(dest, dest, imm.m_value);
+        if (!imm.m_value && !m_fixedWidth)
+            move(MIPSRegisters::zero, dest);
+        else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth)
+            m_assembler.andi(dest, src, imm.m_value);
+        else {
+            move(imm, immTempRegister);
+            m_assembler.andInsn(dest, src, immTempRegister);
+        }
     }
 
     void lshift32(RegisterID shiftAmount, RegisterID dest)
@@ -265,16 +318,38 @@ public:
         m_assembler.sllv(dest, dest, shiftAmount);
     }
 
+    void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.sllv(dest, src, shiftAmount);
+    }
+
+    void lshift32(TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        m_assembler.sllv(dest, dest, immTempRegister);
+    }
+
+    void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        m_assembler.sllv(dest, src, immTempRegister);
+    }
+
     void mul32(RegisterID src, RegisterID dest)
     {
         m_assembler.mul(dest, dest, src);
     }
 
+    void mul32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.mul(dest, op1, op2);
+    }
+
     void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
-        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+        if (!imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
-        else if (!imm.m_isPointer && imm.m_value == 1 && !m_fixedWidth)
+        else if (imm.m_value == 1 && !m_fixedWidth)
             move(src, dest);
         else {
             /*
@@ -291,22 +366,22 @@ public:
         m_assembler.subu(srcDest, MIPSRegisters::zero, srcDest);
     }
 
-    void not32(RegisterID srcDest)
+    void or32(RegisterID src, RegisterID dest)
     {
-        m_assembler.nor(srcDest, srcDest, MIPSRegisters::zero);
+        m_assembler.orInsn(dest, dest, src);
     }
 
-    void or32(RegisterID src, RegisterID dest)
+    void or32(RegisterID op1, RegisterID op2, RegisterID dest)
     {
-        m_assembler.orInsn(dest, dest, src);
+        m_assembler.orInsn(dest, op1, op2);
     }
 
     void or32(TrustedImm32 imm, RegisterID dest)
     {
-        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+        if (!imm.m_value && !m_fixedWidth)
             return;
 
-        if (!imm.m_isPointer && imm.m_value > 0 && imm.m_value < 65535
+        if (imm.m_value > 0 && imm.m_value < 65535
             && !m_fixedWidth) {
             m_assembler.ori(dest, dest, imm.m_value);
             return;
@@ -320,34 +395,84 @@ public:
         m_assembler.orInsn(dest, dest, dataTempRegister);
     }
 
+    void or32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (!imm.m_value && !m_fixedWidth)
+            return;
+
+        if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) {
+            m_assembler.ori(dest, src, imm.m_value);
+            return;
+        }
+
+        /*
+            li      dataTemp, imm
+            or      dest, src, dataTemp
+        */
+        move(imm, dataTempRegister);
+        m_assembler.orInsn(dest, src, dataTempRegister);
+    }
+
+    void or32(RegisterID src, AbsoluteAddress dest)
+    {
+        load32(dest.m_ptr, dataTempRegister);
+        m_assembler.orInsn(dataTempRegister, dataTempRegister, src);
+        store32(dataTempRegister, dest.m_ptr);
+    }
+
     void rshift32(RegisterID shiftAmount, RegisterID dest)
     {
         m_assembler.srav(dest, dest, shiftAmount);
     }
 
+    void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.srav(dest, src, shiftAmount);
+    }
+
     void rshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.sra(dest, dest, imm.m_value);
     }
 
+    void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.sra(dest, src, imm.m_value);
+    }
+
     void urshift32(RegisterID shiftAmount, RegisterID dest)
     {
         m_assembler.srlv(dest, dest, shiftAmount);
     }
 
+    void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest)
+    {
+        m_assembler.srlv(dest, src, shiftAmount);
+    }
+
     void urshift32(TrustedImm32 imm, RegisterID dest)
     {
         m_assembler.srl(dest, dest, imm.m_value);
     }
 
+    void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        m_assembler.srl(dest, src, imm.m_value);
+    }
+
     void sub32(RegisterID src, RegisterID dest)
     {
         m_assembler.subu(dest, dest, src);
     }
 
+    void sub32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.subu(dest, op1, op2);
+    }
+
     void sub32(TrustedImm32 imm, RegisterID dest)
     {
-        if (!imm.m_isPointer && imm.m_value >= -32767 && imm.m_value <= 32768
+        if (imm.m_value >= -32767 && imm.m_value <= 32768
             && !m_fixedWidth) {
             /*
               addiu     dest, src, imm
@@ -363,6 +488,24 @@ public:
         }
     }
 
+    void sub32(RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        if (imm.m_value >= -32767 && imm.m_value <= 32768
+            && !m_fixedWidth) {
+            /*
+              addiu     dest, src, imm
+            */
+            m_assembler.addiu(dest, src, -imm.m_value);
+        } else {
+            /*
+              li        immTemp, imm
+              subu      dest, src, immTemp
+            */
+            move(imm, immTempRegister);
+            m_assembler.subu(dest, src, immTempRegister);
+        }
+    }
+
     void sub32(TrustedImm32 imm, Address address)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -374,15 +517,11 @@ public:
               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);
+            if (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.subu(dataTempRegister, dataTempRegister, immTempRegister);
             }
             m_assembler.sw(dataTempRegister, address.base, address.offset);
         } else {
@@ -398,15 +537,12 @@ public:
             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
+            if (imm.m_value >= -32767 && imm.m_value <= 32768
                 && !m_fixedWidth)
-                m_assembler.addiu(dataTempRegister, dataTempRegister,
-                                  -imm.m_value);
+                m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value);
             else {
                 move(imm, immTempRegister);
-                m_assembler.subu(dataTempRegister, dataTempRegister,
-                                 immTempRegister);
+                m_assembler.subu(dataTempRegister, dataTempRegister, immTempRegister);
             }
             m_assembler.sw(dataTempRegister, addrTempRegister, address.offset);
         }
@@ -430,11 +566,9 @@ public:
         move(TrustedImmPtr(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 {
+        if (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);
         }
@@ -446,8 +580,18 @@ public:
         m_assembler.xorInsn(dest, dest, src);
     }
 
+    void xor32(RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        m_assembler.xorInsn(dest, op1, op2);
+    }
+
     void xor32(TrustedImm32 imm, RegisterID dest)
     {
+        if (imm.m_value == -1) {
+            m_assembler.nor(dest, dest, MIPSRegisters::zero);
+            return;
+        }
+
         /*
             li  immTemp, imm
             xor dest, dest, immTemp
@@ -456,15 +600,49 @@ public:
         m_assembler.xorInsn(dest, dest, immTempRegister);
     }
 
+    void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        if (imm.m_value == -1) {
+            m_assembler.nor(dest, src, MIPSRegisters::zero);
+            return;
+        }
+
+        /*
+            li  immTemp, imm
+            xor dest, dest, immTemp
+        */
+        move(imm, immTempRegister);
+        m_assembler.xorInsn(dest, src, immTempRegister);
+    }
+
     void sqrtDouble(FPRegisterID src, FPRegisterID dst)
     {
         m_assembler.sqrtd(dst, src);
     }
+    
+    void absDouble(FPRegisterID, FPRegisterID)
+    {
+        RELEASE_ASSERT_NOT_REACHED();
+    }
+
+    ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest)
+    {
+        ConvertibleLoadLabel result(this);
+        /*
+            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);
+        return result;
+    }
 
     // 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 TrustedImm32.  Address
+    // store(source, address). The source for a store may be an TrustedImm32. Address
     // operand objects to loads and store will be implicitly constructed if a
     // register is passed.
 
@@ -486,6 +664,77 @@ public:
         }
     }
 
+    void load8(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)(at)
+             */
+            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);
+        }
+    }
+
+    ALWAYS_INLINE void load8(AbsoluteAddress address, RegisterID dest)
+    {
+        load8(address.m_ptr, dest);
+    }
+
+    void load8(const void* address, RegisterID dest)
+    {
+        /*
+            li  addrTemp, address
+            lbu dest, 0(addrTemp)
+        */
+        move(TrustedImmPtr(address), addrTempRegister);
+        m_assembler.lbu(dest, addrTempRegister, 0);
+    }
+
+    void load8Signed(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)(at)
+            */
+            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 load32(ImplicitAddress address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32767
@@ -526,12 +775,16 @@ public:
             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.addu(addrTempRegister, addrTempRegister, immTempRegister);
             m_assembler.lw(dest, addrTempRegister, address.offset);
         }
     }
 
+    void load16Unaligned(BaseIndex address, RegisterID dest)
+    {
+        load16(address, dest);
+    }
+
     void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
     {
         if (address.offset >= -32768 && address.offset <= 32764
@@ -574,8 +827,7 @@ public:
             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);
+            m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
 #if CPU(BIG_ENDIAN)
             m_assembler.lwl(dest, addrTempRegister, 0);
             m_assembler.lwr(dest, addrTempRegister, 3);
@@ -662,12 +914,39 @@ public:
             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.addu(addrTempRegister, addrTempRegister, immTempRegister);
             m_assembler.lhu(dest, addrTempRegister, address.offset);
         }
     }
 
+    void load16Signed(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);
+        }
+    }
+
     DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address)
     {
         m_fixedWidth = true;
@@ -685,112 +964,225 @@ public:
         return dataLabel;
     }
 
-    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)
+    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
-                sw      src, address.offset(addrTemp)
+                sb      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);
+            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
-                sw      src, (address.offset & 0xffff)(at)
+                sb      src, (address.offset & 0xffff)(at)
             */
             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);
+            m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister);
+            m_assembler.sb(src, addrTempRegister, address.offset);
         }
     }
 
-    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, const void* address)
+    void store8(RegisterID src, void* address)
     {
-        /*
-            li  addrTemp, address
-            sw  src, 0(addrTemp)
-        */
         move(TrustedImmPtr(address), addrTempRegister);
-        m_assembler.sw(src, addrTempRegister, 0);
+        m_assembler.sb(src, addrTempRegister, 0);
     }
 
-    void store32(TrustedImm32 imm, const void* address)
+    void store8(TrustedImm32 imm, void* address)
     {
         /*
             li  immTemp, imm
             li  addrTemp, address
-            sw  src, 0(addrTemp)
+            sb  src, 0(addrTemp)
         */
-        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth) {
+        if (!imm.m_value && !m_fixedWidth) {
             move(TrustedImmPtr(address), addrTempRegister);
-            m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
+            m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0);
         } else {
             move(imm, immTempRegister);
             move(TrustedImmPtr(address), addrTempRegister);
-            m_assembler.sw(immTempRegister, addrTempRegister, 0);
+            m_assembler.sb(immTempRegister, addrTempRegister, 0);
+        }
+    }
+
+    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)(at)
+            */
+            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 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)(at)
+            */
+            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, ImplicitAddress address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            if (!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_value && !m_fixedWidth)
+                m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
+            }
+        }
+    }
+
+    void store32(TrustedImm32 imm, 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);
+            if (!imm.m_value)
+                m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset);
+            else {
+                move(imm, immTempRegister);
+                m_assembler.sw(immTempRegister, 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)(at)
+            */
+            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);
+            if (!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, const void* address)
+    {
+        /*
+            li  addrTemp, address
+            sw  src, 0(addrTemp)
+        */
+        move(TrustedImmPtr(address), addrTempRegister);
+        m_assembler.sw(src, addrTempRegister, 0);
+    }
+
+    void store32(TrustedImm32 imm, const void* address)
+    {
+        /*
+            li  immTemp, imm
+            li  addrTemp, address
+            sw  src, 0(addrTemp)
+        */
+        if (!imm.m_value && !m_fixedWidth) {
+            move(TrustedImmPtr(address), addrTempRegister);
+            m_assembler.sw(MIPSRegisters::zero, addrTempRegister, 0);
+        } else {
+            move(imm, immTempRegister);
+            move(TrustedImmPtr(address), addrTempRegister);
+            m_assembler.sw(immTempRegister, addrTempRegister, 0);
         }
     }
 
     // Floating-point operations:
 
-    bool supportsFloatingPoint() const
+    static bool supportsFloatingPoint()
     {
 #if WTF_MIPS_DOUBLE_FLOAT
         return true;
@@ -799,7 +1191,7 @@ public:
 #endif
     }
 
-    bool supportsFloatingPointTruncate() const
+    static bool supportsFloatingPointTruncate()
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
@@ -808,7 +1200,7 @@ public:
 #endif
     }
 
-    bool supportsFloatingPointSqrt() const
+    static bool supportsFloatingPointSqrt()
     {
 #if WTF_MIPS_DOUBLE_FLOAT && WTF_MIPS_ISA_AT_LEAST(2)
         return true;
@@ -816,13 +1208,14 @@ public:
         return false;
 #endif
     }
+    static bool supportsFloatingPointAbs() { return false; }
 
     // Stack manipulation operations:
     //
     // The ABI is assumed to provide a stack abstraction to memory,
-    // containing machine word sized units of data.  Push and pop
+    // 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
+    // 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)
@@ -855,9 +1248,9 @@ public:
 
     void move(TrustedImm32 imm, RegisterID dest)
     {
-        if (!imm.m_isPointer && !imm.m_value && !m_fixedWidth)
+        if (!imm.m_value && !m_fixedWidth)
             move(MIPSRegisters::zero, dest);
-        else if (imm.m_isPointer || m_fixedWidth) {
+        else if (m_fixedWidth) {
             m_assembler.lui(dest, imm.m_value >> 16);
             m_assembler.ori(dest, dest, imm.m_value);
         } else
@@ -921,6 +1314,34 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
+    Jump branch8(RelationalCondition cond, AbsoluteAddress 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);
+    }
+
+    void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest)
+    {
+        // Make sure the immediate value is unsigned 8 bits.
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, dataTempRegister);
+        move(right, immTempRegister);
+        compare32(cond, dataTempRegister, immTempRegister, dest);
+    }
+
+    Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right)
+    {
+        ASSERT(!(right.m_value & 0xFFFFFF00));
+        load8(left, dataTempRegister);
+        // Be careful that the previous load8() uses immTempRegister.
+        // So, we need to put move() after load8().
+        move(right, immTempRegister);
+        return branch32(cond, dataTempRegister, immTempRegister);
+    }
+
     Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right)
     {
         if (cond == Equal)
@@ -1021,22 +1442,6 @@ public:
         return branch32(cond, dataTempRegister, immTempRegister);
     }
 
-    Jump branch16(RelationalCondition cond, BaseIndex left, RegisterID right)
-    {
-        load16(left, dataTempRegister);
-        return branch32(cond, dataTempRegister, right);
-    }
-
-    Jump branch16(RelationalCondition 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(ResultCondition cond, RegisterID reg, RegisterID mask)
     {
         ASSERT((cond == Zero) || (cond == NonZero));
@@ -1070,12 +1475,25 @@ public:
         return branchTest32(cond, dataTempRegister, mask);
     }
 
+    Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        load8(address, dataTempRegister);
+        return branchTest32(cond, dataTempRegister, mask);
+    }
+
     Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, dataTempRegister);
         return branchTest32(cond, dataTempRegister, mask);
     }
 
+    Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1))
+    {
+        move(TrustedImmPtr(address.m_ptr), dataTempRegister);
+        load8(Address(dataTempRegister), dataTempRegister);
+        return branchTest32(cond, dataTempRegister, mask);
+    }
+
     Jump jump()
     {
         return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
@@ -1083,7 +1501,8 @@ public:
 
     void jump(RegisterID target)
     {
-        m_assembler.jr(target);
+        move(target, MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
         m_assembler.nop();
     }
 
@@ -1096,10 +1515,30 @@ public:
         m_fixedWidth = false;
     }
 
+    void jump(AbsoluteAddress address)
+    {
+        m_fixedWidth = true;
+        load32(address.m_ptr, MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
+        m_assembler.nop();
+        m_fixedWidth = false;
+    }
+
+    void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2)
+    {
+        m_assembler.vmov(dest1, dest2, src);
+    }
+
+    void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch)
+    {
+        UNUSED_PARAM(scratch);
+        m_assembler.vmov(dest, src1, src2);
+    }
+
     // Arithmetic control flow operations:
     //
     // This set of conditional branch operations branch based
-    // on the result of an arithmetic operation.  The operation
+    // on the result of an arithmetic operation. The operation
     // is performed as normal, storing the result.
     //
     // * jz operations branch if the result is zero.
@@ -1108,7 +1547,7 @@ public:
 
     Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
-        ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
             /*
                 move    dest, dataTemp
@@ -1141,6 +1580,12 @@ public:
             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
         }
+        if (cond == PositiveOrZero) {
+            add32(src, dest);
+            // Check if dest is not negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
         if (cond == Zero) {
             add32(src, dest);
             return branchEqual(dest, MIPSRegisters::zero);
@@ -1153,12 +1598,182 @@ public:
         return Jump();
     }
 
+    Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            /*
+                move    dataTemp, op1
+                xor     cmpTemp, dataTemp, op2
+                bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
+                addu    dest, dataTemp, op2
+                xor     cmpTemp, dest, dataTemp
+                bgez    cmpTemp, No_overflow    # same sign big -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            move(op1, dataTempRegister);
+            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
+            m_assembler.bltz(cmpTempRegister, 10);
+            m_assembler.addu(dest, dataTempRegister, op2);
+            m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
+            m_assembler.bgez(cmpTempRegister, 7);
+            m_assembler.nop();
+            return jump();
+        }
+        if (cond == Signed) {
+            add32(op1, op2, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == PositiveOrZero) {
+            add32(op1, op2, dest);
+            // Check if dest is not negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            add32(op1, op2, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            add32(op1, op2, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
     Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         move(imm, immTempRegister);
         return branchAdd32(cond, immTempRegister, dest);
     }
 
+    Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        move(src, dest);
+        return branchAdd32(cond, immTempRegister, dest);
+    }
+
+    Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest)
+    {
+        ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero));
+        if (cond == Overflow) {
+            /*
+                move    dataTemp, dest
+                xori    cmpTemp, dataTemp, imm
+                bltz    cmpTemp, No_overflow    # diff sign bit -> no overflow
+                addiu   dataTemp, dataTemp, imm
+                move    dest, dataTemp
+                xori    cmpTemp, dataTemp, imm
+                bgez    cmpTemp, No_overflow    # same sign big -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            if (imm.m_value >= -32768 && imm.m_value  <= 32767 && !m_fixedWidth) {
+                load32(dest.m_ptr, dataTempRegister);
+                m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
+                m_assembler.bltz(cmpTempRegister, 10);
+                m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value);
+                store32(dataTempRegister, dest.m_ptr);
+                m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value);
+                m_assembler.bgez(cmpTempRegister, 7);
+                m_assembler.nop();
+            } else {
+                load32(dest.m_ptr, dataTempRegister);
+                move(imm, immTempRegister);
+                m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister);
+                m_assembler.bltz(cmpTempRegister, 10);
+                m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister);
+                store32(dataTempRegister, dest.m_ptr);
+                m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister);
+                m_assembler.bgez(cmpTempRegister, 7);
+                m_assembler.nop();
+            }
+            return jump();
+        }
+        move(imm, immTempRegister);
+        load32(dest.m_ptr, dataTempRegister);
+        add32(immTempRegister, dataTempRegister);
+        store32(dataTempRegister, dest.m_ptr);
+        if (cond == Signed) {
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == PositiveOrZero) {
+            // Check if dest is not negative.
+            m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero);
+            return branchEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero)
+            return branchEqual(dataTempRegister, MIPSRegisters::zero);
+        if (cond == NonZero)
+            return branchNotEqual(dataTempRegister, MIPSRegisters::zero);
+        ASSERT(0);
+        return Jump();
+    }
+
+    Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, 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(src1, src2);
+            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(src1, src2, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            mul32(src1, src2, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            mul32(src1, src2, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
     Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
@@ -1204,22 +1819,80 @@ public:
         return Jump();
     }
 
-    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
+    Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        return branchMul32(cond, immTempRegister, src, dest);
+    }
+
+    Jump branchSub32(ResultCondition 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(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
     {
         move(imm, immTempRegister);
-        move(src, dest);
-        return branchMul32(cond, immTempRegister, dest);
+        return branchSub32(cond, immTempRegister, dest);
     }
 
-    Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
+    Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
+    {
+        move(imm, immTempRegister);
+        return branchSub32(cond, src, immTempRegister, dest);
+    }
+
+    Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest)
     {
         ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero));
         if (cond == Overflow) {
             /*
-                move    dest, dataTemp
-                xor     cmpTemp, dataTemp, src
+                move    dataTemp, op1
+                xor     cmpTemp, dataTemp, op2
                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
-                subu    dest, dataTemp, src
+                subu    dest, dataTemp, op2
                 xor     cmpTemp, dest, dataTemp
                 bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
                 nop
@@ -1231,37 +1904,37 @@ public:
                 nop
             No_overflow:
             */
-            move(dest, dataTempRegister);
-            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, src);
+            move(op1, dataTempRegister);
+            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
             m_assembler.bgez(cmpTempRegister, 10);
-            m_assembler.subu(dest, dataTempRegister, src);
+            m_assembler.subu(dest, dataTempRegister, op2);
             m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister);
             m_assembler.bgez(cmpTempRegister, 7);
             m_assembler.nop();
             return jump();
         }
         if (cond == Signed) {
-            sub32(src, dest);
+            sub32(op1, op2, dest);
             // Check if dest is negative.
             m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
             return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
         }
         if (cond == Zero) {
-            sub32(src, dest);
+            sub32(op1, op2, dest);
             return branchEqual(dest, MIPSRegisters::zero);
         }
         if (cond == NonZero) {
-            sub32(src, dest);
+            sub32(op1, op2, dest);
             return branchNotEqual(dest, MIPSRegisters::zero);
         }
         ASSERT(0);
         return Jump();
     }
 
-    Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest)
+    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
     {
-        move(imm, immTempRegister);
-        return branchSub32(cond, immTempRegister, dest);
+        m_assembler.li(dataTempRegister, -1);
+        return branchMul32(cond, dataTempRegister, srcDest);
     }
 
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
@@ -1294,7 +1967,7 @@ public:
 
     Call nearCall()
     {
-        /* We need two words for relaxation.  */
+        /* We need two words for relaxation. */
         m_assembler.nop();
         m_assembler.nop();
         m_assembler.jal();
@@ -1313,7 +1986,8 @@ public:
 
     Call call(RegisterID target)
     {
-        m_assembler.jalr(target);
+        move(target, MIPSRegisters::t9);
+        m_assembler.jalr(MIPSRegisters::t9);
         m_assembler.nop();
         return Call(m_assembler.label(), Call::None);
     }
@@ -1382,8 +2056,7 @@ public:
                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
         } else {
             move(mask, immTempRegister);
-            m_assembler.andInsn(cmpTempRegister, dataTempRegister,
-                                immTempRegister);
+            m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister);
             if (cond == Zero)
                 m_assembler.sltiu(dest, cmpTempRegister, 1);
             else
@@ -1402,8 +2075,7 @@ public:
                 m_assembler.sltu(dest, MIPSRegisters::zero, dataTempRegister);
         } else {
             move(mask, immTempRegister);
-            m_assembler.andInsn(cmpTempRegister, dataTempRegister,
-                                immTempRegister);
+            m_assembler.andInsn(cmpTempRegister, dataTempRegister, immTempRegister);
             if (cond == Zero)
                 m_assembler.sltiu(dest, cmpTempRegister, 1);
             else
@@ -1479,6 +2151,34 @@ public:
         return tailRecursiveCall();
     }
 
+    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)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.lwc1(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
+                lwc1    dest, (address.offset & 0xffff)(at)
+            */
+            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);
+        }
+    }
+
     void loadDouble(ImplicitAddress address, FPRegisterID dest)
     {
 #if WTF_MIPS_ISA(1)
@@ -1509,7 +2209,66 @@ public:
 #endif
     }
 
-    void loadDouble(const void* address, FPRegisterID dest)
+    void loadDouble(BaseIndex address, FPRegisterID dest)
+    {
+#if WTF_MIPS_ISA(1)
+        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)
+                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
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                lwc1    dest, (address.offset & 0xffff)(at)
+                lwc1    dest+1, (address.offset & 0xffff + 4)(at)
+            */
+            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.lwc1(FPRegisterID(dest + 1), addrTempRegister, address.offset + 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)(at)
+            */
+            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
+    }
+
+    void loadDouble(TrustedImmPtr address, FPRegisterID dest)
     {
 #if WTF_MIPS_ISA(1)
         /*
@@ -1517,7 +2276,7 @@ public:
             lwc1        dest, 0(addrTemp)
             lwc1        dest+1, 4(addrTemp)
          */
-        move(TrustedImmPtr(address), addrTempRegister);
+        move(address, addrTempRegister);
         m_assembler.lwc1(dest, addrTempRegister, 0);
         m_assembler.lwc1(FPRegisterID(dest + 1), addrTempRegister, 4);
 #else
@@ -1525,11 +2284,38 @@ public:
             li          addrTemp, address
             ldc1        dest, 0(addrTemp)
         */
-        move(TrustedImmPtr(address), addrTempRegister);
+        move(address, addrTempRegister);
         m_assembler.ldc1(dest, addrTempRegister, 0);
 #endif
     }
 
+    void storeFloat(FPRegisterID src, BaseIndex address)
+    {
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                swc1    src, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.swc1(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
+                swc1    src, (address.offset & 0xffff)(at)
+            */
+            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.swc1(src, addrTempRegister, address.offset);
+        }
+    }
 
     void storeDouble(FPRegisterID src, ImplicitAddress address)
     {
@@ -1561,22 +2347,122 @@ public:
 #endif
     }
 
+    void storeDouble(FPRegisterID src, BaseIndex address)
+    {
+#if WTF_MIPS_ISA(1)
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                swc1    src, address.offset(addrTemp)
+                swc1    src+1, (address.offset + 4)(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.swc1(src, addrTempRegister, address.offset);
+            m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4);
+        } else {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                lui     immTemp, (address.offset + 0x8000) >> 16
+                addu    addrTemp, addrTemp, immTemp
+                swc1    src, (address.offset & 0xffff)(at)
+                swc1    src+1, (address.offset & 0xffff + 4)(at)
+            */
+            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.swc1(src, addrTempRegister, address.offset);
+            m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, address.offset + 4);
+        }
+#else
+        if (address.offset >= -32768 && address.offset <= 32767
+            && !m_fixedWidth) {
+            /*
+                sll     addrTemp, address.index, address.scale
+                addu    addrTemp, addrTemp, address.base
+                sdc1    src, address.offset(addrTemp)
+            */
+            m_assembler.sll(addrTempRegister, address.index, address.scale);
+            m_assembler.addu(addrTempRegister, addrTempRegister, address.base);
+            m_assembler.sdc1(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
+                sdc1    src, (address.offset & 0xffff)(at)
+            */
+            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.sdc1(src, addrTempRegister, address.offset);
+        }
+#endif
+    }
+
+    void storeDouble(FPRegisterID src, TrustedImmPtr address)
+    {
+#if WTF_MIPS_ISA(1)
+        move(address, addrTempRegister);
+        m_assembler.swc1(src, addrTempRegister, 0);
+        m_assembler.swc1(FPRegisterID(src + 1), addrTempRegister, 4);
+#else
+        move(address, addrTempRegister);
+        m_assembler.sdc1(src, addrTempRegister, 0);
+#endif
+    }
+
+    void moveDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        if (src != dest || m_fixedWidth)
+            m_assembler.movd(dest, src);
+    }
+
+    void swapDouble(FPRegisterID fr1, FPRegisterID fr2)
+    {
+        moveDouble(fr1, fpTempRegister);
+        moveDouble(fr2, fr1);
+        moveDouble(fpTempRegister, fr2);
+    }
+
     void addDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.addd(dest, dest, src);
     }
 
+    void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.addd(dest, op1, op2);
+    }
+
     void addDouble(Address src, FPRegisterID dest)
     {
         loadDouble(src, fpTempRegister);
         m_assembler.addd(dest, dest, fpTempRegister);
     }
 
+    void addDouble(AbsoluteAddress address, FPRegisterID dest)
+    {
+        loadDouble(TrustedImmPtr(address.m_ptr), fpTempRegister);
+        m_assembler.addd(dest, dest, fpTempRegister);
+    }
+
     void subDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.subd(dest, dest, src);
     }
 
+    void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.subd(dest, op1, op2);
+    }
+
     void subDouble(Address src, FPRegisterID dest)
     {
         loadDouble(src, fpTempRegister);
@@ -1594,11 +2480,32 @@ public:
         m_assembler.muld(dest, dest, fpTempRegister);
     }
 
+    void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.muld(dest, op1, op2);
+    }
+
     void divDouble(FPRegisterID src, FPRegisterID dest)
     {
         m_assembler.divd(dest, dest, src);
     }
 
+    void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest)
+    {
+        m_assembler.divd(dest, op1, op2);
+    }
+
+    void divDouble(Address src, FPRegisterID dest)
+    {
+        loadDouble(src, fpTempRegister);
+        m_assembler.divd(dest, dest, fpTempRegister);
+    }
+
+    void negateDouble(FPRegisterID src, FPRegisterID dest)
+    {
+        m_assembler.negd(dest, src);
+    }
+
     void convertInt32ToDouble(RegisterID src, FPRegisterID dest)
     {
         m_assembler.mtc1(src, fpTempRegister);
@@ -1619,6 +2526,16 @@ public:
         m_assembler.cvtdw(dest, fpTempRegister);
     }
 
+    void convertFloatToDouble(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.cvtds(dst, src);
+    }
+
+    void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst)
+    {
+        m_assembler.cvtsd(dst, src);
+    }
+
     void insertRelaxationWords()
     {
         /* We need four words for relaxation. */
@@ -1648,6 +2565,8 @@ public:
 
     Jump branchEqual(RegisterID rs, RegisterID rt)
     {
+        m_assembler.nop();
+        m_assembler.nop();
         m_assembler.appendJump();
         m_assembler.beq(rs, rt, 0);
         m_assembler.nop();
@@ -1657,6 +2576,8 @@ public:
 
     Jump branchNotEqual(RegisterID rs, RegisterID rt)
     {
+        m_assembler.nop();
+        m_assembler.nop();
         m_assembler.appendJump();
         m_assembler.bne(rs, rt, 0);
         m_assembler.nop();
@@ -1723,24 +2644,47 @@ public:
     // 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)
+    enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful };
+    Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
+    {
+        m_assembler.truncwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+        return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff));
+    }
+
+    Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
+    {
+        m_assembler.truncwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+        return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0));
+    }
+
+    // Result is undefined if the value is outside of the integer range.
+    void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
+    {
+        m_assembler.truncwd(fpTempRegister, src);
+        m_assembler.mfc1(dest, fpTempRegister);
+    }
+
+    // Result is undefined if src > 2^31
+    void truncateDoubleToUint32(FPRegisterID src, RegisterID dest)
     {
         m_assembler.truncwd(fpTempRegister, src);
         m_assembler.mfc1(dest, fpTempRegister);
-        return branch32(Equal, dest, TrustedImm32(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)
+    void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true)
     {
         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));
+        if (negZeroCheck)
+            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);
@@ -1749,33 +2693,93 @@ public:
 
     Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch)
     {
-#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
-        m_assembler.mtc1(MIPSRegisters::zero, scratch);
-        m_assembler.mthc1(MIPSRegisters::zero, scratch);
-#else
-        m_assembler.mtc1(MIPSRegisters::zero, scratch);
-        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
-#endif
+        m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
         return branchDouble(DoubleNotEqual, reg, scratch);
     }
 
     Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch)
     {
-#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64
-        m_assembler.mtc1(MIPSRegisters::zero, scratch);
-        m_assembler.mthc1(MIPSRegisters::zero, scratch);
-#else
-        m_assembler.mtc1(MIPSRegisters::zero, scratch);
-        m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1));
-#endif
+        m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero);
         return branchDouble(DoubleEqualOrUnordered, reg, scratch);
     }
 
+    // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc.
+    static RelationalCondition invert(RelationalCondition cond)
+    {
+        RelationalCondition r;
+        if (cond == Equal)
+            r = NotEqual;
+        else if (cond == NotEqual)
+            r = Equal;
+        else if (cond == Above)
+            r = BelowOrEqual;
+        else if (cond == AboveOrEqual)
+            r = Below;
+        else if (cond == Below)
+            r = AboveOrEqual;
+        else if (cond == BelowOrEqual)
+            r = Above;
+        else if (cond == GreaterThan)
+            r = LessThanOrEqual;
+        else if (cond == GreaterThanOrEqual)
+            r = LessThan;
+        else if (cond == LessThan)
+            r = GreaterThanOrEqual;
+        else if (cond == LessThanOrEqual)
+            r = GreaterThan;
+        return r;
+    }
+
     void nop()
     {
         m_assembler.nop();
     }
 
+    void memoryFence()
+    {
+        m_assembler.sync();
+    }
+
+    static FunctionPtr readCallTarget(CodeLocationCall call)
+    {
+        return FunctionPtr(reinterpret_cast<void(*)()>(MIPSAssembler::readCallTarget(call.dataLocation())));
+    }
+
+    static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
+    {
+        MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation());
+    }
+    
+    static ptrdiff_t maxJumpReplacementSize()
+    {
+        MIPSAssembler::maxJumpReplacementSize();
+        return 0;
+    }
+
+    static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; }
+
+    static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label)
+    {
+        return label.labelAtOffset(0);
+    }
+
+    static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue)
+    {
+        MIPSAssembler::revertJumpToMove(instructionStart.dataLocation(), immTempRegister, reinterpret_cast<int>(initialValue) & 0xffff);
+    }
+
+    static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr)
+    {
+        UNREACHABLE_FOR_PLATFORM();
+        return CodeLocationLabel();
+    }
+
+    static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*)
+    {
+        UNREACHABLE_FOR_PLATFORM();
+    }
+
+
 private:
     // If m_fixedWidth is true, we will generate a fixed number of instructions.
     // Otherwise, we can emit any number of instructions.
@@ -1786,7 +2790,7 @@ private:
 
     static void linkCall(void* code, Call call, FunctionPtr function)
     {
-        MIPSAssembler::linkCall(code, call.m_jmp, function.value());
+        MIPSAssembler::linkCall(code, call.m_label, function.value());
     }
 
     static void repatchCall(CodeLocationCall call, CodeLocationLabel destination)