diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-05-07 11:21:11 +0200 |
commit | 2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47 (patch) | |
tree | 988e8c5b116dd0466244ae2fe5af8ee9be926d76 /Source/JavaScriptCore/assembler | |
parent | dd91e772430dc294e3bf478c119ef8d43c0a3358 (diff) | |
download | qtwebkit-2cf6c8816a73e0132bd8fa3b509d62d7c51b6e47.tar.gz |
Imported WebKit commit 7e538425aa020340619e927792f3d895061fb54b (http://svn.webkit.org/repository/webkit/trunk@116286)
Diffstat (limited to 'Source/JavaScriptCore/assembler')
-rw-r--r-- | Source/JavaScriptCore/assembler/ARMv7Assembler.h | 83 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/AbstractMacroAssembler.h | 59 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/LinkBuffer.h | 28 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssembler.h | 33 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerARM.h | 66 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h | 151 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h | 50 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerSH4.h | 188 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h | 11 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h | 19 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/RepatchBuffer.h | 2 | ||||
-rw-r--r-- | Source/JavaScriptCore/assembler/SH4Assembler.h | 28 |
12 files changed, 541 insertions, 177 deletions
diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index 51788da08..5b523c277 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -531,9 +531,11 @@ private: OP_STR_reg_T1 = 0x5000, OP_STRH_reg_T1 = 0x5200, OP_STRB_reg_T1 = 0x5400, + OP_LDRSB_reg_T1 = 0x5600, OP_LDR_reg_T1 = 0x5800, OP_LDRH_reg_T1 = 0x5A00, OP_LDRB_reg_T1 = 0x5C00, + OP_LDRSH_reg_T1 = 0x5E00, OP_STR_imm_T1 = 0x6000, OP_LDR_imm_T1 = 0x6800, OP_STRB_imm_T1 = 0x7000, @@ -570,7 +572,9 @@ private: OP_CMP_reg_T2 = 0xEBB0, OP_VMOV_CtoD = 0xEC00, OP_VMOV_DtoC = 0xEC10, + OP_FSTS = 0xED00, OP_VSTR = 0xED00, + OP_FLDS = 0xED10, OP_VLDR = 0xED10, OP_VMOV_CtoS = 0xEE00, OP_VMOV_StoC = 0xEE10, @@ -586,6 +590,8 @@ private: OP_VMRS = 0xEEB0, OP_VNEG_T2 = 0xEEB0, OP_VSQRT_T1 = 0xEEB0, + OP_VCVTSD_T1 = 0xEEB0, + OP_VCVTDS_T1 = 0xEEB0, OP_B_T3a = 0xF000, OP_B_T4a = 0xF000, OP_AND_imm_T1 = 0xF000, @@ -627,6 +633,8 @@ private: OP_LDRH_imm_T2 = 0xF8B0, OP_STR_imm_T3 = 0xF8C0, OP_LDR_imm_T3 = 0xF8D0, + OP_LDRSB_reg_T2 = 0xF910, + OP_LDRSH_reg_T2 = 0xF930, OP_LSL_reg_T2 = 0xFA00, OP_LSR_reg_T2 = 0xFA20, OP_ASR_reg_T2 = 0xFA40, @@ -638,10 +646,12 @@ private: typedef enum { OP_VADD_T2b = 0x0A00, OP_VDIVb = 0x0A00, + OP_FLDSb = 0x0A00, OP_VLDRb = 0x0A00, OP_VMOV_IMM_T2b = 0x0A00, OP_VMOV_T2b = 0x0A40, OP_VMUL_T2b = 0x0A00, + OP_FSTSb = 0x0A00, OP_VSTRb = 0x0A00, OP_VMOV_StoCb = 0x0A10, OP_VMOV_CtoSb = 0x0A10, @@ -654,6 +664,8 @@ private: OP_VNEG_T2b = 0x0A40, OP_VSUB_T2b = 0x0A40, OP_VSQRT_T1b = 0x0A40, + OP_VCVTSD_T1b = 0x0A40, + OP_VCVTDS_T1b = 0x0A40, OP_NOP_T2b = 0x8000, OP_B_T3b = 0x8000, OP_B_T4b = 0x9000, @@ -739,6 +751,7 @@ public: ASSERT(imm.isValid()); if (rn == ARMRegisters::sp) { + ASSERT(!(imm.getUInt16() & 3)); if (!(rd & 8) && imm.isUInt10()) { m_formatter.oneWordOp5Reg3Imm8(OP_ADD_SP_imm_T1, rd, static_cast<uint8_t>(imm.getUInt10() >> 2)); return; @@ -1157,6 +1170,30 @@ public: else m_formatter.twoWordOp12Reg4FourFours(OP_LDRB_reg_T2, rn, FourFours(rt, 0, shift, rm)); } + + void ldrsb(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) + { + ASSERT(rn != ARMRegisters::pc); + ASSERT(!BadReg(rm)); + ASSERT(shift <= 3); + + if (!shift && !((rt | rn | rm) & 8)) + m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSB_reg_T1, rm, rn, rt); + else + m_formatter.twoWordOp12Reg4FourFours(OP_LDRSB_reg_T2, rn, FourFours(rt, 0, shift, rm)); + } + + void ldrsh(RegisterID rt, RegisterID rn, RegisterID rm, unsigned shift = 0) + { + ASSERT(rn != ARMRegisters::pc); + ASSERT(!BadReg(rm)); + ASSERT(shift <= 3); + + if (!shift && !((rt | rn | rm) & 8)) + m_formatter.oneWordOp7Reg3Reg3Reg3(OP_LDRSH_reg_T1, rm, rn, rt); + else + m_formatter.twoWordOp12Reg4FourFours(OP_LDRSH_reg_T2, rn, FourFours(rt, 0, shift, rm)); + } void lsl(RegisterID rd, RegisterID rm, int32_t shiftAmount) { @@ -1511,6 +1548,7 @@ public: ASSERT(imm.isValid()); if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { + ASSERT(!(imm.getUInt16() & 3)); m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2)); return; } else if (!((rd | rn) & 8)) { @@ -1572,6 +1610,7 @@ public: ASSERT(imm.isValid()); if ((rn == ARMRegisters::sp) && (rd == ARMRegisters::sp) && imm.isUInt9()) { + ASSERT(!(imm.getUInt16() & 3)); m_formatter.oneWordOp9Imm7(OP_SUB_SP_imm_T1, static_cast<uint8_t>(imm.getUInt9() >> 2)); return; } else if (!((rd | rn) & 8)) { @@ -1689,6 +1728,11 @@ public: { m_formatter.vfpMemOp(OP_VLDR, OP_VLDRb, true, rn, rd, imm); } + + void flds(FPSingleRegisterID rd, RegisterID rn, int32_t imm) + { + m_formatter.vfpMemOp(OP_FLDS, OP_FLDSb, false, rn, rd, imm); + } void vmov(RegisterID rd, FPSingleRegisterID rn) { @@ -1737,6 +1781,11 @@ public: m_formatter.vfpMemOp(OP_VSTR, OP_VSTRb, true, rn, rd, imm); } + void fsts(FPSingleRegisterID rd, RegisterID rn, int32_t imm) + { + m_formatter.vfpMemOp(OP_FSTS, OP_FSTSb, false, rn, rd, imm); + } + void vsub(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) { m_formatter.vfpOp(OP_VSUB_T2, OP_VSUB_T2b, true, rn, rd, rm); @@ -1756,6 +1805,16 @@ public: { m_formatter.vfpOp(OP_VSQRT_T1, OP_VSQRT_T1b, true, VFPOperand(17), rd, rm); } + + void vcvtds(FPDoubleRegisterID rd, FPSingleRegisterID rm) + { + m_formatter.vfpOp(OP_VCVTDS_T1, OP_VCVTDS_T1b, false, VFPOperand(23), rd, rm); + } + + void vcvtsd(FPSingleRegisterID rd, FPDoubleRegisterID rm) + { + m_formatter.vfpOp(OP_VCVTSD_T1, OP_VCVTSD_T1b, true, VFPOperand(23), rd, rm); + } void nop() { @@ -1827,29 +1886,29 @@ public: if (jumpType == JumpCondition) { // 2-byte conditional T1 - const uint16_t* jumpT1Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1))); + const uint16_t* jumpT1Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT1))); if (canBeJumpT1(jumpT1Location, to)) return LinkJumpT1; // 4-byte conditional T3 - const uint16_t* jumpT3Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3))); + const uint16_t* jumpT3Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT3))); if (canBeJumpT3(jumpT3Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkJumpT3; } // 4-byte conditional T4 with IT const uint16_t* conditionalJumpT4Location = - reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4))); + reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkConditionalJumpT4))); if (canBeJumpT4(conditionalJumpT4Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkConditionalJumpT4; } } else { // 2-byte unconditional T2 - const uint16_t* jumpT2Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2))); + const uint16_t* jumpT2Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT2))); if (canBeJumpT2(jumpT2Location, to)) return LinkJumpT2; // 4-byte unconditional T4 - const uint16_t* jumpT4Location = reinterpret_cast<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4))); + const uint16_t* jumpT4Location = reinterpret_cast_ptr<const uint16_t*>(from - (paddingSize - JUMP_ENUM_SIZE(LinkJumpT4))); if (canBeJumpT4(jumpT4Location, to, mayTriggerErrata)) { if (!mayTriggerErrata) return LinkJumpT4; @@ -1888,25 +1947,25 @@ public: { switch (record.linkType()) { case LinkJumpT1: - linkJumpT1(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkJumpT1(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT2: - linkJumpT2(reinterpret_cast<uint16_t*>(from), to); + linkJumpT2(reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT3: - linkJumpT3(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkJumpT3(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkJumpT4: - linkJumpT4(reinterpret_cast<uint16_t*>(from), to); + linkJumpT4(reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkConditionalJumpT4: - linkConditionalJumpT4(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkConditionalJumpT4(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkConditionalBX: - linkConditionalBX(record.condition(), reinterpret_cast<uint16_t*>(from), to); + linkConditionalBX(record.condition(), reinterpret_cast_ptr<uint16_t*>(from), to); break; case LinkBX: - linkBX(reinterpret_cast<uint16_t*>(from), to); + linkBX(reinterpret_cast_ptr<uint16_t*>(from), to); break; default: ASSERT_NOT_REACHED(); diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index ab343977e..4fb60dd2d 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -26,6 +26,7 @@ #ifndef AbstractMacroAssembler_h #define AbstractMacroAssembler_h +#include "AssemblerBuffer.h" #include "CodeLocation.h" #include "MacroAssemblerCodeRef.h" #include <wtf/CryptographicallyRandomNumber.h> @@ -220,33 +221,17 @@ public: struct TrustedImm32 { explicit TrustedImm32(int32_t value) : m_value(value) -#if CPU(ARM) || CPU(MIPS) - , m_isPointer(false) -#endif { } #if !CPU(X86_64) explicit TrustedImm32(TrustedImmPtr ptr) : m_value(ptr.asIntptr()) -#if CPU(ARM) || CPU(MIPS) - , m_isPointer(true) -#endif { } #endif int32_t m_value; -#if CPU(ARM) || CPU(MIPS) - // We rely on being able to regenerate code to recover exception handling - // information. Since ARMv7 supports 16-bit immediates there is a danger - // that if pointer values change the layout of the generated code will change. - // To avoid this problem, always generate pointers (and thus Imm32s constructed - // from ImmPtrs) with a code sequence that is able to represent any pointer - // value - don't use a more compact form in these cases. - // Same for MIPS. - bool m_isPointer; -#endif }; @@ -450,6 +435,12 @@ public: , m_condition(condition) { } +#elif CPU(SH4) + Jump(AssemblerLabel jmp, SH4Assembler::JumpType type = SH4Assembler::JumpFar) + : m_label(jmp) + , m_type(type) + { + } #else Jump(AssemblerLabel jmp) : m_label(jmp) @@ -461,6 +452,8 @@ public: { #if CPU(ARM_THUMB2) masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); +#elif CPU(SH4) + masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type); #else masm->m_assembler.linkJump(m_label, masm->m_assembler.label()); #endif @@ -483,6 +476,24 @@ public: ARMv7Assembler::JumpType m_type; ARMv7Assembler::Condition m_condition; #endif +#if CPU(SH4) + SH4Assembler::JumpType m_type; +#endif + }; + + struct PatchableJump { + PatchableJump() + { + } + + explicit PatchableJump(Jump jump) + : m_jump(jump) + { + } + + operator Jump&() { return m_jump; } + + Jump m_jump; }; // JumpList: @@ -551,7 +562,7 @@ public: } template<typename T, typename U> - ptrdiff_t differenceBetween(T from, U to) + static ptrdiff_t differenceBetween(T from, U to) { return AssemblerType::getDifferenceBetweenLabels(from.m_label, to.m_label); } @@ -561,27 +572,15 @@ public: return reinterpret_cast<ptrdiff_t>(b.executableAddress()) - reinterpret_cast<ptrdiff_t>(a.executableAddress()); } - void beginUninterruptedSequence() { m_inUninterruptedSequence = true; } - void endUninterruptedSequence() { m_inUninterruptedSequence = false; } - unsigned debugOffset() { return m_assembler.debugOffset(); } protected: AbstractMacroAssembler() - : m_inUninterruptedSequence(false) - , m_randomSource(cryptographicallyRandomNumber()) + : m_randomSource(cryptographicallyRandomNumber()) { } AssemblerType m_assembler; - - bool inUninterruptedSequence() - { - return m_inUninterruptedSequence; - } - - bool m_inUninterruptedSequence; - uint32_t random() { diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h index 6ec9a7eb9..5e91ef3ce 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.h +++ b/Source/JavaScriptCore/assembler/LinkBuffer.h @@ -63,6 +63,7 @@ class LinkBuffer { typedef MacroAssemblerCodePtr CodePtr; typedef MacroAssembler::Label Label; typedef MacroAssembler::Jump Jump; + typedef MacroAssembler::PatchableJump PatchableJump; typedef MacroAssembler::JumpList JumpList; typedef MacroAssembler::Call Call; typedef MacroAssembler::DataLabelCompact DataLabelCompact; @@ -154,9 +155,9 @@ public: return CodeLocationNearCall(MacroAssembler::getLinkerAddress(code(), applyOffset(call.m_label))); } - CodeLocationLabel locationOf(Jump jump) + CodeLocationLabel locationOf(PatchableJump jump) { - return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(jump.m_label))); + return CodeLocationLabel(MacroAssembler::getLinkerAddress(code(), applyOffset(jump.m_jump.m_label))); } CodeLocationLabel locationOf(Label label) @@ -260,9 +261,9 @@ private: // Copy the instructions from the last jump to the current one. size_t regionSize = jumpsToLink[i].from() - readPtr; - uint16_t* copySource = reinterpret_cast<uint16_t*>(inData + readPtr); - uint16_t* copyEnd = reinterpret_cast<uint16_t*>(inData + readPtr + regionSize); - uint16_t* copyDst = reinterpret_cast<uint16_t*>(outData + writePtr); + uint16_t* copySource = reinterpret_cast_ptr<uint16_t*>(inData + readPtr); + uint16_t* copyEnd = reinterpret_cast_ptr<uint16_t*>(inData + readPtr + regionSize); + uint16_t* copyDst = reinterpret_cast_ptr<uint16_t*>(outData + writePtr); ASSERT(!(regionSize % 2)); ASSERT(!(readPtr % 2)); ASSERT(!(writePtr % 2)); @@ -374,6 +375,23 @@ private: for (unsigned i = 0; i < tsize; i++) dataLog("\t.short\t0x%x\n", tcode[i]); +#elif CPU(ARM_TRADITIONAL) + // gcc -c jit.s + // objdump -D jit.o + static unsigned codeCount = 0; + unsigned int* tcode = static_cast<unsigned int*>(code); + size_t tsize = size / sizeof(unsigned int); + char nameBuf[128]; + snprintf(nameBuf, sizeof(nameBuf), "_jsc_jit%u", codeCount++); + dataLog("\t.globl\t%s\n" + "\t.align 4\n" + "\t.code 32\n" + "\t.text\n" + "# %p\n" + "%s:\n", nameBuf, code, nameBuf); + + for (unsigned i = 0; i < tsize; i++) + dataLog("\t.long\t0x%x\n", tcode[i]); #endif } #endif diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h index 4c54e29aa..516ffac16 100644 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h @@ -229,6 +229,18 @@ public: branchTestPtr(cond, reg).linkTo(target, this); } +#if !CPU(ARM_THUMB2) + PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) + { + return PatchableJump(branchPtrWithPatch(cond, left, dataLabel, initialRightValue)); + } + + PatchableJump patchableJump() + { + return PatchableJump(jump()); + } +#endif + void jump(Label target) { jump().linkTo(target, this); @@ -529,7 +541,6 @@ public: bool shouldBlind(ImmPtr imm) { - ASSERT(!inUninterruptedSequence()); #if !defined(NDEBUG) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know @@ -636,7 +647,6 @@ public: #if ENABLE(JIT_CONSTANT_BLINDING) bool shouldBlind(Imm32 imm) { - ASSERT(!inUninterruptedSequence()); #if !defined(NDEBUG) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know @@ -699,8 +709,11 @@ public: BlindedImm32 additionBlindedConstant(Imm32 imm) { + // The addition immediate may be used as a pointer offset. Keep aligned based on "imm". + static uint32_t maskTable[4] = { 0xfffffffc, 0xffffffff, 0xfffffffe, 0xffffffff }; + uint32_t baseValue = imm.asTrustedImm32().m_value; - uint32_t key = keyForConstant(baseValue); + uint32_t key = keyForConstant(baseValue) & maskTable[baseValue & 3]; if (key > baseValue) key = key - baseValue; return BlindedImm32(baseValue - key, key); @@ -828,9 +841,17 @@ public: store32(blind.value1, dest); xor32(blind.value2, dest); #else - RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding(); - loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); - store32(scratchRegister, dest); + if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { + loadXorBlindedConstant(xorBlindConstant(imm), scratchRegister); + store32(scratchRegister, dest); + } else { + // If we don't have a scratch register available for use, we'll just + // place a random number of nops. + uint32_t nopCount = random() & 3; + while (nopCount--) + nop(); + store32(imm.asTrustedImm32(), dest); + } #endif } else store32(imm.asTrustedImm32(), dest); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index c0cd766cb..1775cb4cf 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -150,6 +150,11 @@ public: m_assembler.movs_r(dest, m_assembler.lsl(dest, imm.m_value & 0x1f)); } + void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.movs_r(dest, m_assembler.lsl(src, imm.m_value & 0x1f)); + } + void mul32(RegisterID src, RegisterID dest) { if (src == dest) { @@ -180,6 +185,11 @@ public: m_assembler.orrs_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.orrs_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void or32(RegisterID op1, RegisterID op2, RegisterID dest) { m_assembler.orrs_r(dest, op1, op2); @@ -217,6 +227,11 @@ public: { m_assembler.movs_r(dest, m_assembler.lsr(dest, imm.m_value & 0x1f)); } + + void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.movs_r(dest, m_assembler.lsr(src, imm.m_value & 0x1f)); + } void sub32(RegisterID src, RegisterID dest) { @@ -259,6 +274,14 @@ public: m_assembler.eors_r(dest, dest, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); } + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (imm.m_value == -1) + m_assembler.mvns_r(dest, src); + else + m_assembler.eors_r(dest, src, m_assembler.getImm(imm.m_value, ARMRegisters::S0)); + } + void countLeadingZeros32(RegisterID src, RegisterID dest) { #if WTF_ARM_ARCH_AT_LEAST(5) @@ -353,10 +376,7 @@ public: void store32(TrustedImm32 imm, ImplicitAddress address) { - if (imm.m_isPointer) - m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value); - else - move(imm, ARMRegisters::S1); + move(imm, ARMRegisters::S1); store32(ARMRegisters::S1, address); } @@ -369,10 +389,7 @@ public: void store32(TrustedImm32 imm, void* address) { m_assembler.ldr_un_imm(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); - if (imm.m_isPointer) - m_assembler.ldr_un_imm(ARMRegisters::S1, imm.m_value); - else - m_assembler.moveImm(imm.m_value, ARMRegisters::S1); + m_assembler.moveImm(imm.m_value, ARMRegisters::S1); m_assembler.dtr_u(false, ARMRegisters::S1, ARMRegisters::S0, 0); } @@ -400,10 +417,7 @@ public: void move(TrustedImm32 imm, RegisterID dest) { - if (imm.m_isPointer) - m_assembler.ldr_un_imm(dest, imm.m_value); - else - m_assembler.moveImm(imm.m_value, dest); + m_assembler.moveImm(imm.m_value, dest); } void move(RegisterID src, RegisterID dest) @@ -456,16 +470,11 @@ public: Jump branch32(RelationalCondition cond, RegisterID left, TrustedImm32 right, int useConstantPool = 0) { - if (right.m_isPointer) { - m_assembler.ldr_un_imm(ARMRegisters::S0, right.m_value); - m_assembler.cmp_r(left, ARMRegisters::S0); - } else { - ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value); - if (tmp != ARMAssembler::INVALID_IMM) - m_assembler.cmn_r(left, tmp); - else - m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); - } + ARMWord tmp = (right.m_value == 0x80000000) ? ARMAssembler::INVALID_IMM : m_assembler.getOp2(-right.m_value); + if (tmp != ARMAssembler::INVALID_IMM) + m_assembler.cmn_r(left, tmp); + else + m_assembler.cmp_r(left, m_assembler.getImm(right.m_value, ARMRegisters::S0)); return Jump(m_assembler.jmp(ARMCondition(cond), useConstantPool)); } @@ -627,6 +636,13 @@ public: return Jump(m_assembler.jmp(ARMCondition(cond))); } + Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + m_assembler.subs_r(dest, op1, op2); + return Jump(m_assembler.jmp(ARMCondition(cond))); + } + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -687,6 +703,12 @@ public: m_assembler.mov_r(dest, ARMAssembler::getOp2(1), ARMCondition(cond)); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + load8(left, ARMRegisters::S1); + compare32(cond, ARMRegisters::S1, right, dest); + } + void test32(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) { if (mask.m_value == -1) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 43ea2ed5a..3b62cb5be 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -45,6 +45,11 @@ class MacroAssemblerARMv7 : public AbstractMacroAssembler<ARMv7Assembler> { inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); } public: + MacroAssemblerARMv7() + : m_makeJumpPatchable(false) + { + } + typedef ARMv7Assembler::LinkRecord LinkRecord; typedef ARMv7Assembler::JumpType JumpType; typedef ARMv7Assembler::JumpLinkType JumpLinkType; @@ -499,9 +504,10 @@ private: } } - void load16Signed(ArmAddress, RegisterID) + void load16Signed(ArmAddress address, RegisterID dest) { - unreachableForPlatform(); + ASSERT(address.type == ArmAddress::HasIndex); + m_assembler.ldrsh(dest, address.base, address.u.index, address.u.scale); } void load8(ArmAddress address, RegisterID dest) @@ -518,9 +524,10 @@ private: } } - void load8Signed(ArmAddress, RegisterID) + void load8Signed(ArmAddress address, RegisterID dest) { - unreachableForPlatform(); + ASSERT(address.type == ArmAddress::HasIndex); + m_assembler.ldrsb(dest, address.base, address.u.index, address.u.scale); } protected: @@ -609,9 +616,9 @@ public: load8(setupArmAddress(address), dest); } - void load8Signed(BaseIndex, RegisterID) + void load8Signed(BaseIndex address, RegisterID dest) { - unreachableForPlatform(); + load8Signed(setupArmAddress(address), dest); } DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) @@ -649,9 +656,9 @@ public: m_assembler.ldrh(dest, makeBaseIndexBase(address), address.index, address.scale); } - void load16Signed(BaseIndex, RegisterID) + void load16Signed(BaseIndex address, RegisterID dest) { - unreachableForPlatform(); + load16Signed(setupArmAddress(address), dest); } void load16(ImplicitAddress address, RegisterID dest) @@ -722,7 +729,6 @@ public: } #if ENABLE(JIT_CONSTANT_BLINDING) - static RegisterID scratchRegisterForBlinding() { return dataTempRegister; } static bool shouldBlindForSpecificArch(uint32_t value) { ARMThumbImmediate immediate = ARMThumbImmediate::makeEncodedImm(value); @@ -764,18 +770,35 @@ public: m_assembler.vldr(dest, base, offset); } + void loadFloat(ImplicitAddress address, FPRegisterID dest) + { + RegisterID base = address.base; + int32_t offset = address.offset; + + // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. + if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { + add32(TrustedImm32(offset), base, addressTempRegister); + base = addressTempRegister; + offset = 0; + } + + m_assembler.flds(ARMRegisters::asSingle(dest), base, offset); + } + void loadDouble(BaseIndex address, FPRegisterID dest) { - UNUSED_PARAM(address); - UNUSED_PARAM(dest); - unreachableForPlatform(); + move(address.index, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); + add32(address.base, addressTempRegister); + loadDouble(Address(addressTempRegister, address.offset), dest); } void loadFloat(BaseIndex address, FPRegisterID dest) { - UNUSED_PARAM(address); - UNUSED_PARAM(dest); - unreachableForPlatform(); + move(address.index, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); + add32(address.base, addressTempRegister); + loadFloat(Address(addressTempRegister, address.offset), dest); } void moveDouble(FPRegisterID src, FPRegisterID dest) @@ -805,6 +828,21 @@ public: m_assembler.vstr(src, base, offset); } + void storeFloat(FPRegisterID src, ImplicitAddress address) + { + RegisterID base = address.base; + int32_t offset = address.offset; + + // Arm vfp addresses can be offset by a 9-bit ones-comp immediate, left shifted by 2. + if ((offset & 3) || (offset > (255 * 4)) || (offset < -(255 * 4))) { + add32(TrustedImm32(offset), base, addressTempRegister); + base = addressTempRegister; + offset = 0; + } + + m_assembler.fsts(ARMRegisters::asSingle(src), base, offset); + } + void storeDouble(FPRegisterID src, const void* address) { move(TrustedImmPtr(address), addressTempRegister); @@ -814,7 +852,7 @@ public: void storeDouble(FPRegisterID src, BaseIndex address) { move(address.index, addressTempRegister); - mul32(TrustedImm32(1 << address.scale), addressTempRegister, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); add32(address.base, addressTempRegister); storeDouble(src, Address(addressTempRegister, address.offset)); } @@ -822,11 +860,11 @@ public: void storeFloat(FPRegisterID src, BaseIndex address) { move(address.index, addressTempRegister); - mul32(TrustedImm32(1 << address.scale), addressTempRegister, addressTempRegister); + lshift32(TrustedImm32(address.scale), addressTempRegister); add32(address.base, addressTempRegister); - storeDouble(src, Address(addressTempRegister, address.offset)); + storeFloat(src, Address(addressTempRegister, address.offset)); } - + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.vadd(dest, dest, src); @@ -908,7 +946,7 @@ public: void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { - m_assembler.vmov(fpTempRegisterAsSingle(), src); + m_assembler.vmov(fpTempRegister, src, src); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } @@ -916,7 +954,7 @@ public: { // Fixme: load directly into the fpr! load32(address, dataTempRegister); - m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); + m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } @@ -924,22 +962,18 @@ public: { // Fixme: load directly into the fpr! load32(address.m_ptr, dataTempRegister); - m_assembler.vmov(fpTempRegisterAsSingle(), dataTempRegister); + m_assembler.vmov(fpTempRegister, dataTempRegister, dataTempRegister); m_assembler.vcvt_signedToFloatingPoint(dest, fpTempRegisterAsSingle()); } void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) { - UNUSED_PARAM(src); - UNUSED_PARAM(dst); - unreachableForPlatform(); + m_assembler.vcvtds(dst, ARMRegisters::asSingle(src)); } void convertDoubleToFloat(FPRegisterID src, FPRegisterID dst) { - UNUSED_PARAM(src); - UNUSED_PARAM(dst); - unreachableForPlatform(); + m_assembler.vcvtsd(ARMRegisters::asSingle(dst), src); } Jump branchDouble(DoubleCondition cond, FPRegisterID left, FPRegisterID right) @@ -995,8 +1029,17 @@ public: { 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); - return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0)); + 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. @@ -1092,20 +1135,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)); } } @@ -1527,6 +1566,12 @@ public: compare32(cond, dataTempRegister, right, dest); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + load8(left, addressTempRegister); + compare32(cond, addressTempRegister, right, dest); + } + void compare32(RelationalCondition cond, RegisterID left, TrustedImm32 right, RegisterID dest) { compare32(left, right); @@ -1582,6 +1627,22 @@ public: return branch32(cond, addressTempRegister, dataTempRegister); } + PatchableJump patchableBranchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) + { + m_makeJumpPatchable = true; + Jump result = branchPtrWithPatch(cond, left, dataLabel, initialRightValue); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + + PatchableJump patchableJump() + { + m_makeJumpPatchable = true; + Jump result = jump(); + m_makeJumpPatchable = false; + return PatchableJump(result); + } + ALWAYS_INLINE DataLabelPtr storePtrWithPatch(TrustedImmPtr initialValue, ImplicitAddress address) { DataLabelPtr label = moveWithPatch(initialValue, dataTempRegister); @@ -1616,18 +1677,17 @@ public: } protected: - ALWAYS_INLINE Jump jump() { moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); - return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); + return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpNoConditionFixedSize : ARMv7Assembler::JumpNoCondition); } ALWAYS_INLINE Jump makeBranch(ARMv7Assembler::Condition cond) { m_assembler.it(cond, true, true); moveFixedWidthEncoding(TrustedImm32(0), dataTempRegister); - return Jump(m_assembler.bx(dataTempRegister), inUninterruptedSequence() ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); + return Jump(m_assembler.bx(dataTempRegister), m_makeJumpPatchable ? ARMv7Assembler::JumpConditionFixedSize : ARMv7Assembler::JumpCondition, cond); } ALWAYS_INLINE Jump makeBranch(RelationalCondition cond) { return makeBranch(armV7Condition(cond)); } ALWAYS_INLINE Jump makeBranch(ResultCondition cond) { return makeBranch(armV7Condition(cond)); } @@ -1724,6 +1784,7 @@ private: ARMv7Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); } + bool m_makeJumpPatchable; }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index 910bc5a47..f9c3457b5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -116,7 +116,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,8 +148,7 @@ 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); @@ -228,7 +227,7 @@ public: */ move(TrustedImmPtr(address.m_ptr), addrTempRegister); m_assembler.lw(dataTempRegister, addrTempRegister, 0); - 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); else { @@ -245,9 +244,9 @@ public: 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 + else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) m_assembler.andi(dest, dest, imm.m_value); else { @@ -277,9 +276,9 @@ public: 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 +307,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; @@ -357,7 +356,7 @@ public: 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 +374,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,8 +401,7 @@ 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 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); @@ -426,8 +424,7 @@ 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); @@ -458,7 +455,7 @@ 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 + if (imm.m_value >= -32767 && imm.m_value <= 32768 && !m_fixedWidth) { m_assembler.addiu(dataTempRegister, dataTempRegister, -imm.m_value); @@ -807,7 +804,7 @@ public: { if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { - if (!imm.m_isPointer && !imm.m_value) + if (!imm.m_value) m_assembler.sw(MIPSRegisters::zero, address.base, address.offset); else { @@ -822,7 +819,7 @@ 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) + if (!imm.m_value && !m_fixedWidth) m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); else { @@ -850,7 +847,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 { @@ -928,9 +925,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 +991,15 @@ public: return branch32(cond, dataTempRegister, immTempRegister); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + // Make sure the immediate value is unsigned 8 bits. + ASSERT(!(right.m_value & 0xFFFFFF00)); + load8(left, dataTempRegister); + move(right, immTempRegister); + compare32(cond, dataTempRegister, immTempRegister, dest); + } + Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { ASSERT(!(right.m_value & 0xFFFFFF00)); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h index 2b5c0cc44..c132ad642 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h @@ -156,6 +156,17 @@ public: releaseScratch(scr); } + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + and32(src, dest); + return; + } + + and32(imm, dest); + } + void lshift32(RegisterID shiftamount, RegisterID dest) { if (shiftamount == SH4Registers::r0) @@ -193,6 +204,14 @@ public: releaseScratch(scr); } + void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) + { + if (src != dest) + move(src, dest); + + lshift32(shiftamount, dest); + } + void mul32(RegisterID src, RegisterID dest) { m_assembler.imullRegReg(src, dest); @@ -239,6 +258,29 @@ public: } } + +void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + or32(src, dest); + return; + } + + or32(imm, dest); + } + + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (src != dest) { + move(imm, dest); + xor32(src, dest); + return; + } + + xor32(imm, dest); + } + void rshift32(RegisterID shiftamount, RegisterID dest) { if (shiftamount == SH4Registers::r0) @@ -681,8 +723,7 @@ public: load8(scr, scr1); add32(TrustedImm32(1), scr); load8(scr, dest); - move(TrustedImm32(8), scr); - m_assembler.shllRegReg(dest, scr); + m_assembler.shllImm8r(8, dest); or32(scr1, dest); releaseScratch(scr); @@ -942,6 +983,12 @@ public: void load32WithUnalignedHalfWords(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); + RegisterID scr1 = claimScratch(); + Jump m_jump; + JumpList end; + + if (dest != SH4Registers::r0) + move(SH4Registers::r0, scr1); move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); @@ -950,13 +997,44 @@ public: if (address.offset) add32(TrustedImm32(address.offset), scr); - RegisterID scr1 = claimScratch(); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 68, sizeof(uint32_t)); + move(scr, SH4Registers::r0); + m_assembler.andlImm8r(0x3, SH4Registers::r0); + m_assembler.cmpEqImmR0(0x0, SH4Registers::r0); + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + load32(scr, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + m_assembler.andlImm8r(0x1, SH4Registers::r0); + m_assembler.cmpEqImmR0(0x0, SH4Registers::r0); + + if (dest != SH4Registers::r0) + move(scr1, SH4Registers::r0); + + m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); load16(scr, scr1); add32(TrustedImm32(2), scr); load16(scr, dest); - move(TrustedImm32(16), scr); - m_assembler.shllRegReg(dest, scr); + m_assembler.shllImm8r(16, dest); or32(scr1, dest); + end.append(Jump(m_assembler.bra(), SH4Assembler::JumpNear)); + m_assembler.nop(); + m_jump.link(this); + load8(scr, scr1); + add32(TrustedImm32(1), scr); + load16(scr, dest); + m_assembler.shllImm8r(8, dest); + or32(dest, scr1); + add32(TrustedImm32(2), scr); + load8(scr, dest); + m_assembler.shllImm8r(8, dest); + m_assembler.shllImm8r(16, dest); + or32(scr1, dest); + end.link(this); releaseScratch(scr); releaseScratch(scr1); @@ -999,19 +1077,22 @@ public: if (cond == DoubleNotEqual) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 8); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 4); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); releaseScratch(scr); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleGreaterThan) { @@ -1036,113 +1117,135 @@ public: if (cond == DoubleEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(left, right); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleGreaterThanOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleGreaterThanOrEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } if (cond == DoubleLessThanOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); + Jump m_jump = Jump(m_assembler.je()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchTrue(); + return m_jump; } if (cond == DoubleLessThanOrEqualOrUnordered) { RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } ASSERT(cond == DoubleNotEqualOrUnordered); RegisterID scr = claimScratch(); + JumpList end; m_assembler.loadConstant(0x7fbfffff, scratchReg3); m_assembler.dcnvds(right); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 5); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcnvds(left); m_assembler.stsfpulReg(scr); m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - m_assembler.branch(BT_OPCODE, 1); + end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); + Jump m_jump = Jump(m_assembler.jne()); + end.link(this); + m_assembler.extraInstrForBranch(scr); releaseScratch(scr); - return branchFalse(); + return m_jump; } Jump branchTrue() { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.je()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1150,9 +1253,7 @@ public: { m_assembler.ensureSpace(m_assembler.maxInstructionSize + 6, sizeof(uint32_t)); Jump m_jump = Jump(m_assembler.jne()); - m_assembler.loadConstantUnReusable(0x0, scratchReg3); - m_assembler.nop(); - m_assembler.nop(); + m_assembler.extraInstrForBranch(scratchReg3); return m_jump; } @@ -1207,6 +1308,14 @@ public: return jmp; } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + RegisterID addressTempRegister = claimScratch(); + load8(left, addressTempRegister); + compare32(cond, addressTempRegister, right, dest); + releaseScratch(addressTempRegister); + } + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) { m_assembler.ftrcdrmfpul(src); @@ -1677,6 +1786,13 @@ public: return branchSub32(cond, scratchReg3, dest); } + Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 != dest) + move(src1, dest); + return branchSub32(cond, src2, dest); + } + Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1738,6 +1854,14 @@ public: releaseScratch(scr); } + void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) + { + if (src != dest) + move(src, dest); + + urshift32(shiftamount, dest); + } + Call call() { return Call(m_assembler.call(), Call::Linkable); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 8cb442cc5..e398dcdad 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -129,6 +129,11 @@ public: { m_assembler.addl_rm(src, dest.offset, dest.base); } + + void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + m_assembler.leal_mr(imm.m_value, src, dest); + } void and32(RegisterID src, RegisterID dest) { @@ -1348,6 +1353,12 @@ public: m_assembler.ret(); } + void compare8(RelationalCondition cond, Address left, TrustedImm32 right, RegisterID dest) + { + m_assembler.cmpb_im(right.m_value, left.offset, left.base); + set32(x86Condition(cond), dest); + } + void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) { m_assembler.cmpl_rr(right, left); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h index a2b4311e5..41479f996 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h @@ -402,7 +402,7 @@ public: m_assembler.testq_rr(reg, mask); return Jump(m_assembler.jCC(x86Condition(cond))); } - + Jump branchTestPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1)) { // if we are only interested in the low seven bits, this can be tested with a testb @@ -415,6 +415,23 @@ public: return Jump(m_assembler.jCC(x86Condition(cond))); } + void testPtr(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest) + { + if (mask.m_value == -1) + m_assembler.testq_rr(reg, reg); + else if ((mask.m_value & ~0x7f) == 0) + m_assembler.testb_i8r(mask.m_value, reg); + else + m_assembler.testq_i32r(mask.m_value, reg); + set32(x86Condition(cond), dest); + } + + void testPtr(ResultCondition cond, RegisterID reg, RegisterID mask, RegisterID dest) + { + m_assembler.testq_rr(reg, mask); + set32(x86Condition(cond), dest); + } + Jump branchTestPtr(ResultCondition cond, AbsoluteAddress address, TrustedImm32 mask = TrustedImm32(-1)) { loadPtr(address.m_ptr, scratchRegister); diff --git a/Source/JavaScriptCore/assembler/RepatchBuffer.h b/Source/JavaScriptCore/assembler/RepatchBuffer.h index e56185fdb..a87294b1b 100644 --- a/Source/JavaScriptCore/assembler/RepatchBuffer.h +++ b/Source/JavaScriptCore/assembler/RepatchBuffer.h @@ -26,7 +26,7 @@ #ifndef RepatchBuffer_h #define RepatchBuffer_h -#if ENABLE(ASSEMBLER) +#if ENABLE(JIT) #include "CodeBlock.h" #include <MacroAssembler.h> diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h index 1cf96b735..11e954cad 100644 --- a/Source/JavaScriptCore/assembler/SH4Assembler.h +++ b/Source/JavaScriptCore/assembler/SH4Assembler.h @@ -326,6 +326,10 @@ public: padForAlign32 = 0x00090009, }; + enum JumpType { JumpFar, + JumpNear + }; + SH4Assembler() { m_claimscratchReg = 0x0; @@ -1188,6 +1192,13 @@ public: return label; } + void extraInstrForBranch(RegisterID dst) + { + loadConstantUnReusable(0x0, dst); + nop(); + nop(); + } + AssemblerLabel jmp(RegisterID dst) { jmpReg(dst); @@ -1215,6 +1226,13 @@ public: return label; } + AssemblerLabel bra() + { + AssemblerLabel label = m_buffer.label(); + branch(BRA_OPCODE, 0); + return label; + } + void ret() { m_buffer.ensureSpace(maxInstructionSize + 2); @@ -1424,7 +1442,7 @@ public: // Linking & patching - void linkJump(AssemblerLabel from, AssemblerLabel to) + void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar) { ASSERT(to.isSet()); ASSERT(from.isSet()); @@ -1433,6 +1451,14 @@ public: uint16_t instruction = *instructionPtr; int offsetBits; + if (type == JumpNear) { + ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE)); + int offset = (codeSize() - from.m_offset) - 4; + *instructionPtr++ = instruction | (offset >> 1); + printInstr(*instructionPtr, from.m_offset + 2); + return; + } + if (((instruction & 0xff00) == BT_OPCODE) || ((instruction & 0xff00) == BF_OPCODE)) { /* BT label => BF 2 nop LDR reg |