X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/6fe7ccc865dc7d7541b93c5bcaf6368d2c98a174..refs/heads/master:/assembler/MacroAssemblerARMv7.h diff --git a/assembler/MacroAssemblerARMv7.h b/assembler/MacroAssemblerARMv7.h index b72717a..2e71e61 100644 --- a/assembler/MacroAssemblerARMv7.h +++ b/assembler/MacroAssemblerARMv7.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2014 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -34,12 +34,9 @@ namespace JSC { -class MacroAssemblerARMv7 : public AbstractMacroAssembler { - // 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. +class MacroAssemblerARMv7 : public AbstractMacroAssembler { static const RegisterID dataTempRegister = ARMRegisters::ip; - static const RegisterID addressTempRegister = ARMRegisters::r3; + static const RegisterID addressTempRegister = ARMRegisters::r6; static const ARMRegisters::FPDoubleRegisterID fpTempRegister = ARMRegisters::d7; inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); } @@ -53,18 +50,23 @@ public: typedef ARMv7Assembler::LinkRecord LinkRecord; typedef ARMv7Assembler::JumpType JumpType; typedef ARMv7Assembler::JumpLinkType JumpLinkType; - // Magic number is the biggest useful offset we can get on ARMv7 with - // a LDR_imm_T2 encoding - static const int MaximumCompactPtrAlignedAddressOffset = 124; - - Vector& jumpsToLink() { return m_assembler.jumpsToLink(); } + typedef ARMv7Assembler::Condition Condition; + + static const ARMv7Assembler::Condition DefaultCondition = ARMv7Assembler::ConditionInvalid; + static const ARMv7Assembler::JumpType DefaultJump = ARMv7Assembler::JumpNoConditionFixedSize; + + static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) + { + return value >= -255 && value <= 255; + } + + Vector& jumpsToLink() { return m_assembler.jumpsToLink(); } void* unlinkedCode() { return m_assembler.unlinkedCode(); } - bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); } - JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); } - JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(record, from, to); } - void recordLinkOffsets(int32_t regionStart, int32_t regionEnd, int32_t offset) {return m_assembler.recordLinkOffsets(regionStart, regionEnd, offset); } - int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return m_assembler.jumpSizeDelta(jumpType, jumpLinkType); } - void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return m_assembler.link(record, from, to); } + static bool canCompact(JumpType jumpType) { return ARMv7Assembler::canCompact(jumpType); } + static JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(jumpType, from, to); } + static JumpLinkType computeJumpType(LinkRecord& record, const uint8_t* from, const uint8_t* to) { return ARMv7Assembler::computeJumpType(record, from, to); } + static int jumpSizeDelta(JumpType jumpType, JumpLinkType jumpLinkType) { return ARMv7Assembler::jumpSizeDelta(jumpType, jumpLinkType); } + static void link(LinkRecord& record, uint8_t* from, uint8_t* to) { return ARMv7Assembler::link(record, from, to); } struct ArmAddress { enum AddressType { @@ -97,8 +99,6 @@ public: }; public: - typedef ARMRegisters::FPDoubleRegisterID FPRegisterID; - static const Scale ScalePtr = TimesFour; enum RelationalCondition { @@ -117,6 +117,7 @@ public: enum ResultCondition { Overflow = ARMv7Assembler::ConditionVS, Signed = ARMv7Assembler::ConditionMI, + PositiveOrZero = ARMv7Assembler::ConditionPL, Zero = ARMv7Assembler::ConditionEQ, NonZero = ARMv7Assembler::ConditionNE }; @@ -139,6 +140,7 @@ public: }; static const RegisterID stackPointerRegister = ARMRegisters::sp; + static const RegisterID framePointerRegister = ARMRegisters::fp; static const RegisterID linkRegister = ARMRegisters::lr; // Integer arithmetic operations: @@ -157,10 +159,24 @@ public: { add32(imm, dest, dest); } + + void add32(AbsoluteAddress src, RegisterID dest) + { + load32(src.m_ptr, dataTempRegister); + add32(dataTempRegister, dest); + } void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { ARMThumbImmediate armImm = ARMThumbImmediate::makeUInt12OrEncodedImm(imm.m_value); + + // For adds with stack pointer destination, moving the src first to sp is + // needed to avoid unpredictable instruction + if (dest == ARMRegisters::sp && src != dest) { + move(src, ARMRegisters::sp); + src = ARMRegisters::sp; + } + if (armImm.isValid()) m_assembler.add(dest, src, armImm); else { @@ -209,6 +225,11 @@ public: store32(dataTempRegister, address.m_ptr); } + void addPtrNoFlags(TrustedImm32 imm, RegisterID srcDest) + { + add32(imm, srcDest); + } + void add64(TrustedImm32 imm, AbsoluteAddress address) { move(TrustedImmPtr(address.m_ptr), addressTempRegister); @@ -255,6 +276,12 @@ public: and32(imm, dest, dest); } + void and32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + and32(dataTempRegister, dest); + } + void countLeadingZeros32(RegisterID src, RegisterID dest) { m_assembler.clz(dest, src); @@ -305,6 +332,21 @@ public: { m_assembler.orr(dest, dest, src); } + + void or32(RegisterID src, AbsoluteAddress dest) + { + move(TrustedImmPtr(dest.m_ptr), addressTempRegister); + load32(addressTempRegister, dataTempRegister); + or32(src, dataTempRegister); + store32(dataTempRegister, addressTempRegister); + } + + void or32(TrustedImm32 imm, Address address) + { + load32(address, dataTempRegister); + or32(imm, dataTempRegister, dataTempRegister); + store32(dataTempRegister, address); + } void or32(TrustedImm32 imm, RegisterID dest) { @@ -504,7 +546,7 @@ private: } } - void load16Signed(ArmAddress address, RegisterID dest) + void load16SignedExtendTo32(ArmAddress address, RegisterID dest) { ASSERT(address.type == ArmAddress::HasIndex); m_assembler.ldrsh(dest, address.base, address.u.index, address.u.scale); @@ -524,7 +566,7 @@ private: } } - void load8Signed(ArmAddress address, RegisterID dest) + void load8SignedExtendTo32(ArmAddress address, RegisterID dest) { ASSERT(address.type == ArmAddress::HasIndex); m_assembler.ldrsb(dest, address.base, address.u.index, address.u.scale); @@ -600,15 +642,35 @@ public: move(TrustedImmPtr(address), addressTempRegister); m_assembler.ldr(dest, addressTempRegister, ARMThumbImmediate::makeUInt16(0)); } + + void abortWithReason(AbortReason reason) + { + move(TrustedImm32(reason), dataTempRegister); + breakpoint(); + } + + void abortWithReason(AbortReason reason, intptr_t misc) + { + move(TrustedImm32(misc), addressTempRegister); + abortWithReason(reason); + } + + ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) + { + ConvertibleLoadLabel result(this); + ASSERT(address.offset >= 0 && address.offset <= 255); + m_assembler.ldrWide8BitImmediate(dest, address.base, address.offset); + return result; + } void load8(ImplicitAddress address, RegisterID dest) { load8(setupArmAddress(address), dest); } - void load8Signed(ImplicitAddress, RegisterID) + void load8SignedExtendTo32(ImplicitAddress, RegisterID) { - unreachableForPlatform(); + UNREACHABLE_FOR_PLATFORM(); } void load8(BaseIndex address, RegisterID dest) @@ -616,9 +678,15 @@ public: load8(setupArmAddress(address), dest); } - void load8Signed(BaseIndex address, RegisterID dest) + void load8SignedExtendTo32(BaseIndex address, RegisterID dest) + { + load8SignedExtendTo32(setupArmAddress(address), dest); + } + + void load8(const void* address, RegisterID dest) { - load8Signed(setupArmAddress(address), dest); + move(TrustedImmPtr(address), dest); + load8(dest, dest); } DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) @@ -628,26 +696,16 @@ public: return label; } - // FIXME: we should be able to plant a compact load relative to/from any base/dest register. DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) { + padBeforePatch(); + RegisterID base = address.base; - if (base >= ARMRegisters::r8) { - move(base, addressTempRegister); - base = addressTempRegister; - } - DataLabelCompact label(this); - ASSERT(address.offset >= 0); - ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset); - ASSERT(ARMThumbImmediate::makeUInt12(address.offset).isUInt7()); + ASSERT(isCompactPtrAlignedAddressOffset(address.offset)); - if (dest >= ARMRegisters::r8) { - m_assembler.ldrCompact(addressTempRegister, base, ARMThumbImmediate::makeUInt12(address.offset)); - move(addressTempRegister, dest); - } else - m_assembler.ldrCompact(dest, base, ARMThumbImmediate::makeUInt12(address.offset)); + m_assembler.ldr(dest, base, address.offset, true, false); return label; } @@ -656,9 +714,9 @@ public: m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale); } - void load16Signed(BaseIndex address, RegisterID dest) + void load16SignedExtendTo32(BaseIndex address, RegisterID dest) { - load16Signed(setupArmAddress(address), dest); + load16SignedExtendTo32(setupArmAddress(address), dest); } void load16(ImplicitAddress address, RegisterID dest) @@ -672,9 +730,9 @@ public: } } - void load16Signed(ImplicitAddress, RegisterID) + void load16SignedExtendTo32(ImplicitAddress, RegisterID) { - unreachableForPlatform(); + UNREACHABLE_FOR_PLATFORM(); } DataLabel32 store32WithAddressOffsetPatch(RegisterID src, Address address) @@ -718,17 +776,51 @@ public: store32(dataTempRegister, address); } + void store8(RegisterID src, Address address) + { + store8(src, setupArmAddress(address)); + } + void store8(RegisterID src, BaseIndex address) { store8(src, setupArmAddress(address)); } + void store8(RegisterID src, void* address) + { + move(TrustedImmPtr(address), addressTempRegister); + store8(src, ArmAddress(addressTempRegister, 0)); + } + + void store8(TrustedImm32 imm, void* address) + { + move(imm, dataTempRegister); + store8(dataTempRegister, address); + } + + void store8(TrustedImm32 imm, Address address) + { + move(imm, dataTempRegister); + store8(dataTempRegister, address); + } + void store16(RegisterID src, BaseIndex address) { store16(src, setupArmAddress(address)); } -#if ENABLE(JIT_CONSTANT_BLINDING) + // Possibly clobbers src, but not on this architecture. + 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); + } + static bool shouldBlindForSpecificArch(uint32_t value) { ARMThumbImmediate immediate = ARMThumbImmediate::makeEncodedImm(value); @@ -746,7 +838,6 @@ public: // be controlled by an attacker. return !immediate.isUInt12(); } -#endif // Floating-point operations: @@ -807,9 +898,9 @@ public: m_assembler.vmov(dest, src); } - void loadDouble(const void* address, FPRegisterID dest) + void loadDouble(TrustedImmPtr address, FPRegisterID dest) { - move(TrustedImmPtr(address), addressTempRegister); + move(address, addressTempRegister); m_assembler.vldr(dest, addressTempRegister, 0); } @@ -843,9 +934,9 @@ public: m_assembler.fsts(ARMRegisters::asSingle(src), base, offset); } - void storeDouble(FPRegisterID src, const void* address) + void storeDouble(FPRegisterID src, TrustedImmPtr address) { - move(TrustedImmPtr(address), addressTempRegister); + move(address, addressTempRegister); storeDouble(src, addressTempRegister); } @@ -883,7 +974,7 @@ public: void addDouble(AbsoluteAddress address, FPRegisterID dest) { - loadDouble(address.m_ptr, fpTempRegister); + loadDouble(TrustedImmPtr(address.m_ptr), fpTempRegister); m_assembler.vadd(dest, dest, fpTempRegister); } @@ -1025,23 +1116,6 @@ public: return failure; } - Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) - { - m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); - m_assembler.vmov(dest, fpTempRegisterAsSingle()); - - Jump overflow = branch32(Equal, dest, TrustedImm32(0x7fffffff)); - Jump success = branch32(GreaterThanOrEqual, dest, TrustedImm32(0)); - overflow.link(this); - - if (branchType == BranchIfTruncateSuccessful) - return success; - - Jump failure = jump(); - success.link(this); - return failure; - } - // Result is undefined if the value is outside of the integer range. void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) { @@ -1059,7 +1133,7 @@ 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, 0). - void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID) + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true) { m_assembler.vcvt_floatingPointToSigned(fpTempRegisterAsSingle(), src); m_assembler.vmov(dest, fpTempRegisterAsSingle()); @@ -1069,7 +1143,8 @@ public: failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, fpTempRegister)); // If the result is zero, it might have been -0.0, and the double comparison won't catch this! - failureCases.append(branchTest32(Zero, dest)); + if (negZeroCheck) + failureCases.append(branchTest32(Zero, dest)); } Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID) @@ -1105,14 +1180,12 @@ public: void pop(RegisterID dest) { - // store postindexed with writeback - m_assembler.ldr(dest, ARMRegisters::sp, sizeof(void*), false, true); + m_assembler.pop(dest); } void push(RegisterID src) { - // store preindexed with writeback - m_assembler.str(src, ARMRegisters::sp, -sizeof(void*), true, true); + m_assembler.push(src); } void push(Address address) @@ -1127,6 +1200,16 @@ public: push(dataTempRegister); } + void popPair(RegisterID dest1, RegisterID dest2) + { + m_assembler.pop(1 << dest1 | 1 << dest2); + } + + void pushPair(RegisterID src1, RegisterID src2) + { + m_assembler.push(1 << src1 | 1 << src2); + } + // Register move operations: // // Move values in registers. @@ -1135,20 +1218,16 @@ public: { uint32_t value = imm.m_value; - if (imm.m_isPointer) - moveFixedWidthEncoding(imm, dest); - else { - ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(value); + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(value); - if (armImm.isValid()) - m_assembler.mov(dest, armImm); - else if ((armImm = ARMThumbImmediate::makeEncodedImm(~value)).isValid()) - m_assembler.mvn(dest, armImm); - else { - m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(value)); - if (value & 0xffff0000) - m_assembler.movt(dest, ARMThumbImmediate::makeUInt16(value >> 16)); - } + if (armImm.isValid()) + m_assembler.mov(dest, armImm); + else if ((armImm = ARMThumbImmediate::makeEncodedImm(~value)).isValid()) + m_assembler.mvn(dest, armImm); + else { + m_assembler.mov(dest, ARMThumbImmediate::makeUInt16(value)); + if (value & 0xffff0000) + m_assembler.movt(dest, ARMThumbImmediate::makeUInt16(value >> 16)); } } @@ -1190,6 +1269,21 @@ public: { m_assembler.nop(); } + + void memoryFence() + { + m_assembler.dmbSY(); + } + + static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) + { + ARMv7Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); + } + + static ptrdiff_t maxJumpReplacementSize() + { + return ARMv7Assembler::maxJumpReplacementSize(); + } // Forwards / external control flow operations: // @@ -1214,18 +1308,14 @@ private: void compare32(RegisterID left, TrustedImm32 right) { int32_t imm = right.m_value; - if (!imm) - m_assembler.tst(left, left); + ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm); + if (armImm.isValid()) + m_assembler.cmp(left, armImm); + else if ((armImm = ARMThumbImmediate::makeEncodedImm(-imm)).isValid()) + m_assembler.cmn(left, armImm); else { - ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm); - if (armImm.isValid()) - m_assembler.cmp(left, armImm); - else if ((armImm = ARMThumbImmediate::makeEncodedImm(-imm)).isValid()) - m_assembler.cmn(left, armImm); - else { - move(TrustedImm32(imm), dataTempRegister); - m_assembler.cmp(left, dataTempRegister); - } + move(TrustedImm32(imm), dataTempRegister); + m_assembler.cmp(left, dataTempRegister); } } @@ -1237,16 +1327,34 @@ private: m_assembler.tst(reg, reg); else { ARMThumbImmediate armImm = ARMThumbImmediate::makeEncodedImm(imm); - if (armImm.isValid()) - m_assembler.tst(reg, armImm); - else { + if (armImm.isValid()) { + if (reg == ARMRegisters::sp) { + move(reg, addressTempRegister); + m_assembler.tst(addressTempRegister, armImm); + } else + m_assembler.tst(reg, armImm); + } else { move(mask, dataTempRegister); - m_assembler.tst(reg, dataTempRegister); + if (reg == ARMRegisters::sp) { + move(reg, addressTempRegister); + m_assembler.tst(addressTempRegister, dataTempRegister); + } else + m_assembler.tst(reg, dataTempRegister); } } } public: + void test32(ResultCondition, RegisterID reg, TrustedImm32 mask) + { + test32(reg, mask); + } + + Jump branch(ResultCondition cond) + { + return Jump(makeBranch(cond)); + } + Jump branch32(RelationalCondition cond, RegisterID left, RegisterID right) { m_assembler.cmp(left, right); @@ -1305,6 +1413,12 @@ public: return branch32(cond, addressTempRegister, right); } + Jump branchPtr(RelationalCondition cond, BaseIndex left, RegisterID right) + { + load32(left, dataTempRegister); + return branch32(cond, dataTempRegister, right); + } + Jump branch8(RelationalCondition cond, RegisterID left, TrustedImm32 right) { compare32(left, right); @@ -1327,6 +1441,14 @@ public: return branch32(cond, addressTempRegister, right); } + Jump branch8(RelationalCondition cond, AbsoluteAddress address, TrustedImm32 right) + { + // Use addressTempRegister instead of dataTempRegister, since branch32 uses dataTempRegister. + move(TrustedImmPtr(address.m_ptr), addressTempRegister); + load8(Address(addressTempRegister), addressTempRegister); + return branch32(cond, addressTempRegister, right); + } + Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) { m_assembler.tst(reg, mask); @@ -1353,6 +1475,13 @@ public: return branchTest32(cond, addressTempRegister, mask); } + Jump branchTest8(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) + { + // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + load8(address, addressTempRegister); + return branchTest32(cond, addressTempRegister, mask); + } + Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) { // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ @@ -1360,6 +1489,14 @@ public: return branchTest32(cond, addressTempRegister, mask); } + Jump branchTest8(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) + { + // use addressTempRegister incase the branchTest8 we call uses dataTempRegister. :-/ + move(TrustedImmPtr(address.m_ptr), addressTempRegister); + load8(Address(addressTempRegister), addressTempRegister); + return branchTest32(cond, addressTempRegister, mask); + } + void jump(RegisterID target) { m_assembler.bx(target); @@ -1413,6 +1550,12 @@ public: return branchAdd32(cond, dest, src, dest); } + Jump branchAdd32(ResultCondition cond, Address src, RegisterID dest) + { + load32(src, dataTempRegister); + return branchAdd32(cond, dest, dataTempRegister, dest); + } + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { return branchAdd32(cond, dest, imm, dest); @@ -1608,12 +1751,14 @@ public: ALWAYS_INLINE DataLabel32 moveWithPatch(TrustedImm32 imm, RegisterID dst) { + padBeforePatch(); moveFixedWidthEncoding(imm, dst); return DataLabel32(this); } ALWAYS_INLINE DataLabelPtr moveWithPatch(TrustedImmPtr imm, RegisterID dst) { + padBeforePatch(); moveFixedWidthEncoding(TrustedImm32(imm), dst); return DataLabelPtr(this); } @@ -1630,6 +1775,37 @@ public: dataLabel = moveWithPatch(initialRightValue, dataTempRegister); return branch32(cond, addressTempRegister, dataTempRegister); } + + ALWAYS_INLINE Jump branch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0)) + { + load32(left, addressTempRegister); + dataLabel = moveWithPatch(initialRightValue, dataTempRegister); + return branch32(cond, addressTempRegister, dataTempRegister); + } + + PatchableJump patchableBranchPtr(RelationalCondition cond, Address left, TrustedImmPtr right = TrustedImmPtr(0)) + { + m_makeJumpPatchable = true; + Jump result = branch32(cond, left, TrustedImm32(right)); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + + PatchableJump patchableBranchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) + { + m_makeJumpPatchable = true; + Jump result = branchTest32(cond, reg, mask); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + + PatchableJump patchableBranch32(RelationalCondition cond, RegisterID reg, TrustedImm32 imm) + { + m_makeJumpPatchable = true; + Jump result = branch32(cond, reg, imm); + m_makeJumpPatchable = false; + return PatchableJump(result); + } PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { @@ -1639,8 +1815,17 @@ public: return PatchableJump(result); } + PatchableJump patchableBranch32WithPatch(RelationalCondition cond, Address left, DataLabel32& dataLabel, TrustedImm32 initialRightValue = TrustedImm32(0)) + { + m_makeJumpPatchable = true; + Jump result = branch32WithPatch(cond, left, dataLabel, initialRightValue); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + PatchableJump patchableJump() { + padBeforePatch(); m_makeJumpPatchable = true; Jump result = jump(); m_makeJumpPatchable = false; @@ -1670,25 +1855,72 @@ public: } - int executableOffsetFor(int location) + static FunctionPtr readCallTarget(CodeLocationCall call) { - return m_assembler.executableOffsetFor(location); + return FunctionPtr(reinterpret_cast(ARMv7Assembler::readCallTarget(call.dataLocation()))); + } + + static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } + static bool canJumpReplacePatchableBranch32WithPatch() { return false; } + + static CodeLocationLabel startOfBranchPtrWithPatchOnRegister(CodeLocationDataLabelPtr label) + { + const unsigned twoWordOpSize = 4; + return label.labelAtOffset(-twoWordOpSize * 2); + } + + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue) + { +#if OS(LINUX) + ARMv7Assembler::revertJumpTo_movT3movtcmpT2(instructionStart.dataLocation(), rd, dataTempRegister, reinterpret_cast(initialValue)); +#else + UNUSED_PARAM(rd); + ARMv7Assembler::revertJumpTo_movT3(instructionStart.dataLocation(), dataTempRegister, ARMThumbImmediate::makeUInt16(reinterpret_cast(initialValue) & 0xffff)); +#endif + } + + static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static CodeLocationLabel startOfPatchableBranch32WithPatchOnAddress(CodeLocationDataLabel32) + { + UNREACHABLE_FOR_PLATFORM(); + return CodeLocationLabel(); + } + + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) + { + UNREACHABLE_FOR_PLATFORM(); } - static FunctionPtr readCallTarget(CodeLocationCall call) + static void revertJumpReplacementToPatchableBranch32WithPatch(CodeLocationLabel, Address, int32_t) { - return FunctionPtr(reinterpret_cast(ARMv7Assembler::readCallTarget(call.dataLocation()))); + UNREACHABLE_FOR_PLATFORM(); } +#if ENABLE(MASM_PROBE) + // Methods required by the MASM_PROBE mechanism as defined in + // AbstractMacroAssembler.h. + static void printCPURegisters(CPUState&, int indentation = 0); + static void printRegister(CPUState&, RegisterID); + static void printRegister(CPUState&, FPRegisterID); + void probe(ProbeFunction, void* arg1 = 0, void* arg2 = 0); +#endif // ENABLE(MASM_PROBE) + protected: ALWAYS_INLINE Jump jump() { + m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint. moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); } ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond) { + m_assembler.label(); // Force nop-padding if we're in the middle of a watchpoint. m_assembler.it(cond, true, true); moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); @@ -1788,6 +2020,23 @@ private: ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); } +#if ENABLE(MASM_PROBE) + inline TrustedImm32 trustedImm32FromPtr(void* ptr) + { + return TrustedImm32(TrustedImmPtr(ptr)); + } + + inline TrustedImm32 trustedImm32FromPtr(ProbeFunction function) + { + return TrustedImm32(TrustedImmPtr(reinterpret_cast(function))); + } + + inline TrustedImm32 trustedImm32FromPtr(void (*function)()) + { + return TrustedImm32(TrustedImmPtr(reinterpret_cast(function))); + } +#endif + bool m_makeJumpPatchable; };