]> git.saurik.com Git - apple/javascriptcore.git/blobdiff - assembler/MacroAssemblerARMv7.h
JavaScriptCore-576.tar.gz
[apple/javascriptcore.git] / assembler / MacroAssemblerARMv7.h
index f7a84027f75dff8f81653054830c334002422de9..532a9cfd2883a4e6d6e01a6a6aad264f45bcb22d 100644 (file)
@@ -39,9 +39,9 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> {
     // FIXME: switch dataTempRegister & addressTempRegister, or possibly use r7?
     //        - dTR is likely used more than aTR, and we'll get better instruction
     //        encoding if it's in the low 8 registers.
-    static const ARM::RegisterID dataTempRegister = ARM::ip;
-    static const RegisterID addressTempRegister = ARM::r3;
-    static const FPRegisterID fpTempRegister = ARM::d7;
+    static const ARMRegisters::RegisterID dataTempRegister = ARMRegisters::ip;
+    static const RegisterID addressTempRegister = ARMRegisters::r3;
+    static const FPRegisterID fpTempRegister = ARMRegisters::d7;
 
     struct ArmAddress {
         enum AddressType {
@@ -93,17 +93,25 @@ public:
         Zero = ARMv7Assembler::ConditionEQ,
         NonZero = ARMv7Assembler::ConditionNE
     };
-
     enum DoubleCondition {
+        // These conditions will only evaluate to true if the comparison is ordered - i.e. neither operand is NaN.
         DoubleEqual = ARMv7Assembler::ConditionEQ,
+        DoubleNotEqual = ARMv7Assembler::ConditionVC, // Not the right flag! check for this & handle differently.
         DoubleGreaterThan = ARMv7Assembler::ConditionGT,
         DoubleGreaterThanOrEqual = ARMv7Assembler::ConditionGE,
         DoubleLessThan = ARMv7Assembler::ConditionLO,
         DoubleLessThanOrEqual = ARMv7Assembler::ConditionLS,
+        // If either operand is NaN, these conditions always evaluate to true.
+        DoubleEqualOrUnordered = ARMv7Assembler::ConditionVS, // Not the right flag! check for this & handle differently.
+        DoubleNotEqualOrUnordered = ARMv7Assembler::ConditionNE,
+        DoubleGreaterThanOrUnordered = ARMv7Assembler::ConditionHI,
+        DoubleGreaterThanOrEqualOrUnordered = ARMv7Assembler::ConditionHS,
+        DoubleLessThanOrUnordered = ARMv7Assembler::ConditionLT,
+        DoubleLessThanOrEqualOrUnordered = ARMv7Assembler::ConditionLE,
     };
 
-    static const RegisterID stackPointerRegister = ARM::sp;
-    static const RegisterID linkRegister = ARM::lr;
+    static const RegisterID stackPointerRegister = ARMRegisters::sp;
+    static const RegisterID linkRegister = ARMRegisters::lr;
 
     // Integer arithmetic operations:
     //
@@ -189,14 +197,19 @@ public:
         }
     }
 
-    void lshift32(Imm32 imm, RegisterID dest)
+    void lshift32(RegisterID shift_amount, RegisterID dest)
     {
-        m_assembler.lsl(dest, dest, imm.m_value);
+        // Clamp the shift to the range 0..31
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
+        ASSERT(armImm.isValid());
+        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+
+        m_assembler.lsl(dest, dest, dataTempRegister);
     }
 
-    void lshift32(RegisterID shift_amount, RegisterID dest)
+    void lshift32(Imm32 imm, RegisterID dest)
     {
-        m_assembler.lsl(dest, dest, shift_amount);
+        m_assembler.lsl(dest, dest, imm.m_value & 0x1f);
     }
 
     void mul32(RegisterID src, RegisterID dest)
@@ -233,12 +246,17 @@ public:
 
     void rshift32(RegisterID shift_amount, RegisterID dest)
     {
-        m_assembler.asr(dest, dest, shift_amount);
+        // Clamp the shift to the range 0..31
+        ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(0x1f);
+        ASSERT(armImm.isValid());
+        m_assembler.ARM_and(dataTempRegister, shift_amount, armImm);
+
+        m_assembler.asr(dest, dest, dataTempRegister);
     }
 
     void rshift32(Imm32 imm, RegisterID dest)
     {
-        m_assembler.asr(dest, dest, imm.m_value);
+        m_assembler.asr(dest, dest, imm.m_value & 0x1f);
     }
 
     void sub32(RegisterID src, RegisterID dest)
@@ -375,6 +393,11 @@ public:
         load32(setupArmAddress(address), dest);
     }
 
+    void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest)
+    {
+        load32(setupArmAddress(address), dest);
+    }
+
     void load32(void* address, RegisterID dest)
     {
         move(ImmPtr(address), addressTempRegister);
@@ -526,12 +549,30 @@ public:
     {
         m_assembler.vcmp_F64(left, right);
         m_assembler.vmrs_APSR_nzcv_FPSCR();
+
+        if (cond == DoubleNotEqual) {
+            // ConditionNE jumps if NotEqual *or* unordered - force the unordered cases not to jump.
+            Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
+            Jump result = makeBranch(ARMv7Assembler::ConditionNE);
+            unordered.link(this);
+            return result;
+        }
+        if (cond == DoubleEqualOrUnordered) {
+            Jump unordered = makeBranch(ARMv7Assembler::ConditionVS);
+            Jump notEqual = makeBranch(ARMv7Assembler::ConditionNE);
+            unordered.link(this);
+            // We get here if either unordered, or equal.
+            Jump result = makeJump();
+            notEqual.link(this);
+            return result;
+        }
         return makeBranch(cond);
     }
 
     Jump branchTruncateDoubleToInt32(FPRegisterID, RegisterID)
     {
         ASSERT_NOT_REACHED();
+        return jump();
     }
 
 
@@ -546,13 +587,13 @@ public:
     void pop(RegisterID dest)
     {
         // store postindexed with writeback
-        m_assembler.ldr(dest, ARM::sp, sizeof(void*), false, true);
+        m_assembler.ldr(dest, ARMRegisters::sp, sizeof(void*), false, true);
     }
 
     void push(RegisterID src)
     {
         // store preindexed with writeback
-        m_assembler.str(src, ARM::sp, -sizeof(void*), true, true);
+        m_assembler.str(src, ARMRegisters::sp, -sizeof(void*), true, true);
     }
 
     void push(Address address)
@@ -716,6 +757,13 @@ public:
         return branch32(cond, addressTempRegister, right);
     }
 
+    Jump branch32WithUnalignedHalfWords(Condition cond, BaseIndex left, Imm32 right)
+    {
+        // use addressTempRegister incase the branch32 we call uses dataTempRegister. :-/
+        load32WithUnalignedHalfWords(left, addressTempRegister);
+        return branch32(cond, addressTempRegister, right);
+    }
+
     Jump branch32(Condition cond, AbsoluteAddress left, RegisterID right)
     {
         load32(left.m_ptr, dataTempRegister);
@@ -977,13 +1025,15 @@ public:
 protected:
     ARMv7Assembler::JmpSrc makeJump()
     {
-        return m_assembler.b();
+        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+        return m_assembler.bx(dataTempRegister);
     }
 
     ARMv7Assembler::JmpSrc makeBranch(ARMv7Assembler::Condition cond)
     {
-        m_assembler.it(cond);
-        return m_assembler.b();
+        m_assembler.it(cond, true, true);
+        moveFixedWidthEncoding(Imm32(0), dataTempRegister);
+        return m_assembler.bx(dataTempRegister);
     }
     ARMv7Assembler::JmpSrc makeBranch(Condition cond) { return makeBranch(armV7Condition(cond)); }
     ARMv7Assembler::JmpSrc makeBranch(DoubleCondition cond) { return makeBranch(armV7Condition(cond)); }
@@ -1038,7 +1088,7 @@ protected:
         return addressTempRegister;
     }
 
-    DataLabel32 moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
+    void moveFixedWidthEncoding(Imm32 imm, RegisterID dst)
     {
         uint32_t value = imm.m_value;
         m_assembler.movT3(dst, ARMThumbImmediate::makeUInt16(value & 0xffff));