]> 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 0a63c2928734f82025f8829c8da96d105141e49f..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
@@ -148,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 {
@@ -173,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);
         }
@@ -190,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) {
@@ -222,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 {
             /*
@@ -260,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)
@@ -270,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 {
             /*
@@ -308,10 +378,10 @@ public:
 
     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;
@@ -325,11 +395,41 @@ 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);
@@ -345,19 +445,34 @@ public:
         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
@@ -375,7 +490,7 @@ public:
 
     void sub32(RegisterID src, 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
@@ -402,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 {
@@ -426,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);
         }
@@ -458,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);
         }
@@ -474,6 +580,11 @@ 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) {
@@ -489,6 +600,21 @@ 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);
@@ -496,13 +622,27 @@ public:
     
     void absDouble(FPRegisterID, FPRegisterID)
     {
-        ASSERT_NOT_REACHED();
+        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.
 
@@ -547,12 +687,54 @@ 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.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
@@ -593,8 +775,7 @@ 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);
         }
     }
@@ -646,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);
@@ -734,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;
@@ -757,6 +964,85 @@ public:
         return dataLabel;
     }
 
+    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)(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.sb(src, addrTempRegister, address.offset);
+        }
+    }
+
+    void store8(RegisterID src, void* address)
+    {
+        move(TrustedImmPtr(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_value && !m_fixedWidth) {
+            move(TrustedImmPtr(address), addrTempRegister);
+            m_assembler.sb(MIPSRegisters::zero, addrTempRegister, 0);
+        } else {
+            move(imm, immTempRegister);
+            move(TrustedImmPtr(address), addrTempRegister);
+            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
@@ -797,8 +1083,7 @@ 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.sw(src, addrTempRegister, address.offset);
         }
     }
@@ -807,9 +1092,8 @@ public:
     {
         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);
+            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);
@@ -822,17 +1106,53 @@ public:
               */
             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);
+            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);
+                m_assembler.sw(immTempRegister, addrTempRegister, address.offset);
             }
         }
     }
 
+
     void store32(RegisterID src, const void* address)
     {
         /*
@@ -850,7 +1170,7 @@ public:
             li  addrTemp, address
             sw  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);
         } else {
@@ -893,9 +1213,9 @@ public:
     // 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)
@@ -928,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
@@ -994,6 +1314,15 @@ 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.
@@ -1146,20 +1475,34 @@ public:
         return branchTest32(cond, dataTempRegister, mask);
     }
 
-    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
+    Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1))
     {
         load8(address, dataTempRegister);
         return branchTest32(cond, dataTempRegister, mask);
     }
 
-    Jump jump()
+    Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
     {
-        return branchEqual(MIPSRegisters::zero, MIPSRegisters::zero);
-    }
+        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);
+    }
 
     void jump(RegisterID target)
     {
-        m_assembler.jr(target);
+        move(target, MIPSRegisters::t9);
+        m_assembler.jr(MIPSRegisters::t9);
         m_assembler.nop();
     }
 
@@ -1172,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.
@@ -1184,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
@@ -1217,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);
@@ -1229,6 +1598,59 @@ 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);
@@ -1242,6 +1664,116 @@ public:
         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));
@@ -1290,8 +1822,7 @@ public:
     Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest)
     {
         move(imm, immTempRegister);
-        move(src, dest);
-        return branchMul32(cond, immTempRegister, dest);
+        return branchMul32(cond, immTempRegister, src, dest);
     }
 
     Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest)
@@ -1350,8 +1881,60 @@ public:
     Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest)
     {
         move(imm, immTempRegister);
-        move(src, dest);
-        return branchSub32(cond, immTempRegister, dest);
+        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    dataTemp, op1
+                xor     cmpTemp, dataTemp, op2
+                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
+                subu    dest, dataTemp, op2
+                xor     cmpTemp, dest, dataTemp
+                bgez    cmpTemp, No_overflow    # same sign bit -> no overflow
+                nop
+                b       Overflow
+                nop
+                nop
+                nop
+                nop
+                nop
+            No_overflow:
+            */
+            move(op1, dataTempRegister);
+            m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2);
+            m_assembler.bgez(cmpTempRegister, 10);
+            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(op1, op2, dest);
+            // Check if dest is negative.
+            m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero);
+            return branchNotEqual(cmpTempRegister, MIPSRegisters::zero);
+        }
+        if (cond == Zero) {
+            sub32(op1, op2, dest);
+            return branchEqual(dest, MIPSRegisters::zero);
+        }
+        if (cond == NonZero) {
+            sub32(op1, op2, dest);
+            return branchNotEqual(dest, MIPSRegisters::zero);
+        }
+        ASSERT(0);
+        return Jump();
+    }
+
+    Jump branchNeg32(ResultCondition cond, RegisterID srcDest)
+    {
+        m_assembler.li(dataTempRegister, -1);
+        return branchMul32(cond, dataTempRegister, srcDest);
     }
 
     Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest)
@@ -1384,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();
@@ -1403,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);
     }
@@ -1472,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
@@ -1492,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
@@ -1569,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)
@@ -1599,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)
         /*
@@ -1607,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
@@ -1615,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)
     {
@@ -1651,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);
@@ -1684,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);
@@ -1709,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. */
@@ -1738,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();
@@ -1747,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();
@@ -1813,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);
@@ -1839,38 +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.