diff options
Diffstat (limited to 'Source/JavaScriptCore/assembler')
19 files changed, 1373 insertions, 892 deletions
diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.cpp b/Source/JavaScriptCore/assembler/ARMAssembler.cpp index 6912d1ea3..4f4199bf2 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.cpp +++ b/Source/JavaScriptCore/assembler/ARMAssembler.cpp @@ -391,14 +391,14 @@ void ARMAssembler::baseIndexTransferFloat(DataTransferTypeFloat transferType, FP dataTransferFloat(transferType, srcDst, ARMRegisters::S1, offset); } -PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) +PassRefPtr<ExecutableMemoryHandle> ARMAssembler::executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { // 64-bit alignment is required for next constant pool and JIT code as well m_buffer.flushWithoutBarrier(true); if (!m_buffer.isAligned(8)) bkpt(0); - RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort); + RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(vm, ownerUID, effort); char* data = reinterpret_cast<char*>(result->start()); for (Jumps::Iterator iter = m_jumps.begin(); iter != m_jumps.end(); ++iter) { diff --git a/Source/JavaScriptCore/assembler/ARMAssembler.h b/Source/JavaScriptCore/assembler/ARMAssembler.h index 31d316d0d..c950e47bb 100644 --- a/Source/JavaScriptCore/assembler/ARMAssembler.h +++ b/Source/JavaScriptCore/assembler/ARMAssembler.h @@ -107,21 +107,21 @@ namespace JSC { // ARM conditional constants typedef enum { - EQ = 0x00000000, // Zero - NE = 0x10000000, // Non-zero - CS = 0x20000000, - CC = 0x30000000, - MI = 0x40000000, - PL = 0x50000000, - VS = 0x60000000, - VC = 0x70000000, - HI = 0x80000000, - LS = 0x90000000, - GE = 0xa0000000, - LT = 0xb0000000, - GT = 0xc0000000, - LE = 0xd0000000, - AL = 0xe0000000 + EQ = 0x00000000, // Zero / Equal. + NE = 0x10000000, // Non-zero / Not equal. + CS = 0x20000000, // Unsigned higher or same. + CC = 0x30000000, // Unsigned lower. + MI = 0x40000000, // Negative. + PL = 0x50000000, // Positive or zero. + VS = 0x60000000, // Overflowed. + VC = 0x70000000, // Not overflowed. + HI = 0x80000000, // Unsigned higher. + LS = 0x90000000, // Unsigned lower or same. + GE = 0xa0000000, // Signed greater than or equal. + LT = 0xb0000000, // Signed less than. + GT = 0xc0000000, // Signed greater than. + LE = 0xd0000000, // Signed less than or equal. + AL = 0xe0000000 // Unconditional / Always execute. } Condition; // ARM instruction constants @@ -760,7 +760,7 @@ namespace JSC { return loadBranchTarget(ARMRegisters::pc, cc, useConstantPool); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData&, void* ownerUID, JITCompilationEffort); + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM&, void* ownerUID, JITCompilationEffort); unsigned debugOffset() { return m_buffer.debugOffset(); } @@ -1022,29 +1022,46 @@ namespace JSC { return AL | B | (offset & BranchOffsetMask); } +#if OS(LINUX) && COMPILER(GCC) + static inline void linuxPageFlush(uintptr_t begin, uintptr_t end) + { + asm volatile( + "push {r7}\n" + "mov r0, %0\n" + "mov r1, %1\n" + "mov r7, #0xf0000\n" + "add r7, r7, #0x2\n" + "mov r2, #0x0\n" + "svc 0x0\n" + "pop {r7}\n" + : + : "r" (begin), "r" (end) + : "r0", "r1", "r2"); + } +#endif + #if OS(LINUX) && COMPILER(RVCT) static __asm void cacheFlush(void* code, size_t); #else static void cacheFlush(void* code, size_t size) { #if OS(LINUX) && COMPILER(GCC) - uintptr_t currentPage = reinterpret_cast<uintptr_t>(code) & ~(pageSize() - 1); - uintptr_t lastPage = (reinterpret_cast<uintptr_t>(code) + size) & ~(pageSize() - 1); - do { - asm volatile( - "push {r7}\n" - "mov r0, %0\n" - "mov r1, %1\n" - "mov r7, #0xf0000\n" - "add r7, r7, #0x2\n" - "mov r2, #0x0\n" - "svc 0x0\n" - "pop {r7}\n" - : - : "r" (currentPage), "r" (currentPage + pageSize()) - : "r0", "r1", "r2"); - currentPage += pageSize(); - } while (lastPage >= currentPage); + size_t page = pageSize(); + uintptr_t current = reinterpret_cast<uintptr_t>(code); + uintptr_t end = current + size; + uintptr_t firstPageEnd = (current & ~(page - 1)) + page; + + if (end <= firstPageEnd) { + linuxPageFlush(current, end); + return; + } + + linuxPageFlush(current, firstPageEnd); + + for (current = firstPageEnd; current + page < end; current += page) + linuxPageFlush(current, current + page); + + linuxPageFlush(current, end); #elif OS(WINCE) CacheRangeFlush(code, size, CACHE_SYNC_ALL); #elif OS(QNX) && ENABLE(ASSEMBLER_WX_EXCLUSIVE) diff --git a/Source/JavaScriptCore/assembler/ARMv7Assembler.h b/Source/JavaScriptCore/assembler/ARMv7Assembler.h index aa402e208..28989549d 100644 --- a/Source/JavaScriptCore/assembler/ARMv7Assembler.h +++ b/Source/JavaScriptCore/assembler/ARMv7Assembler.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009, 2010, 2012 Apple Inc. All rights reserved. + * Copyright (C) 2009, 2010, 2012, 2013 Apple Inc. All rights reserved. * Copyright (C) 2010 University of Szeged * * Redistribution and use in source and binary forms, with or without @@ -422,21 +422,21 @@ public: // (HS, LO, HI, LS) -> (AE, B, A, BE) // (VS, VC) -> (O, NO) typedef enum { - ConditionEQ, - ConditionNE, - ConditionHS, ConditionCS = ConditionHS, - ConditionLO, ConditionCC = ConditionLO, - ConditionMI, - ConditionPL, - ConditionVS, - ConditionVC, - ConditionHI, - ConditionLS, - ConditionGE, - ConditionLT, - ConditionGT, - ConditionLE, - ConditionAL, + ConditionEQ, // Zero / Equal. + ConditionNE, // Non-zero / Not equal. + ConditionHS, ConditionCS = ConditionHS, // Unsigned higher or same. + ConditionLO, ConditionCC = ConditionLO, // Unsigned lower. + ConditionMI, // Negative. + ConditionPL, // Positive or zero. + ConditionVS, // Overflowed. + ConditionVC, // Not overflowed. + ConditionHI, // Unsigned higher. + ConditionLS, // Unsigned lower or same. + ConditionGE, // Signed greater than or equal. + ConditionLT, // Signed less than. + ConditionGT, // Signed greater than. + ConditionLE, // Signed less than or equal. + ConditionAL, // Unconditional / Always execute. ConditionInvalid } Condition; @@ -661,6 +661,10 @@ private: OP_ROR_reg_T2 = 0xFA60, OP_CLZ = 0xFAB0, OP_SMULL_T1 = 0xFB80, +#if CPU(APPLE_ARMV7S) + OP_SDIV_T1 = 0xFB90, + OP_UDIV_T1 = 0xFBB0, +#endif } OpcodeID1; typedef enum { @@ -1403,6 +1407,16 @@ public: m_formatter.twoWordOp12Reg4FourFours(OP_ROR_reg_T2, rn, FourFours(0xf, rd, 0, rm)); } +#if CPU(APPLE_ARMV7S) + ALWAYS_INLINE void sdiv(RegisterID rd, RegisterID rn, RegisterID rm) + { + ASSERT(!BadReg(rd)); + ASSERT(!BadReg(rn)); + ASSERT(!BadReg(rm)); + m_formatter.twoWordOp12Reg4FourFours(OP_SDIV_T1, rn, FourFours(0xf, rd, 0xf, rm)); + } +#endif + ALWAYS_INLINE void smull(RegisterID rdLo, RegisterID rdHi, RegisterID rn, RegisterID rm) { ASSERT(!BadReg(rdLo)); @@ -1739,6 +1753,16 @@ public: m_formatter.twoWordOp12Reg40Imm3Reg4Imm20Imm5(OP_UBFX_T1, rd, rn, (lsb & 0x1c) << 10, (lsb & 0x3) << 6, (width - 1) & 0x1f); } +#if CPU(APPLE_ARMV7S) + ALWAYS_INLINE void udiv(RegisterID rd, RegisterID rn, RegisterID rm) + { + ASSERT(!BadReg(rd)); + ASSERT(!BadReg(rn)); + ASSERT(!BadReg(rm)); + m_formatter.twoWordOp12Reg4FourFours(OP_UDIV_T1, rn, FourFours(0xf, rd, 0xf, rm)); + } +#endif + void vadd(FPDoubleRegisterID rd, FPDoubleRegisterID rn, FPDoubleRegisterID rm) { m_formatter.vfpOp(OP_VADD_T2, OP_VADD_T2b, true, rn, rd, rm); @@ -2011,7 +2035,7 @@ public: offsets[ptr++] = offset; } - Vector<LinkRecord>& jumpsToLink() + Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink() { std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator); return m_jumpsToLink; @@ -2042,7 +2066,7 @@ public: linkBX(reinterpret_cast_ptr<uint16_t*>(from), to); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); break; } } @@ -2202,7 +2226,7 @@ public: cacheFlush(ptr, sizeof(uint16_t) * 2); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -2222,17 +2246,15 @@ public: case OP_ADD_imm_T3: break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } unsigned debugOffset() { return m_formatter.debugOffset(); } - static void cacheFlush(void* code, size_t size) +#if OS(LINUX) + static inline void linuxPageFlush(uintptr_t begin, uintptr_t end) { -#if OS(IOS) - sys_cache_control(kCacheFunctionPrepareForExecution, code, size); -#elif OS(LINUX) asm volatile( "push {r7}\n" "mov r0, %0\n" @@ -2243,8 +2265,32 @@ public: "svc 0x0\n" "pop {r7}\n" : - : "r" (code), "r" (reinterpret_cast<char*>(code) + size) + : "r" (begin), "r" (end) : "r0", "r1", "r2"); + } +#endif + + static void cacheFlush(void* code, size_t size) + { +#if OS(IOS) + sys_cache_control(kCacheFunctionPrepareForExecution, code, size); +#elif OS(LINUX) + size_t page = pageSize(); + uintptr_t current = reinterpret_cast<uintptr_t>(code); + uintptr_t end = current + size; + uintptr_t firstPageEnd = (current & ~(page - 1)) + page; + + if (end <= firstPageEnd) { + linuxPageFlush(current, end); + return; + } + + linuxPageFlush(current, firstPageEnd); + + for (current = firstPageEnd; current + page < end; current += page) + linuxPageFlush(current, current + page); + + linuxPageFlush(current, end); #elif OS(WINCE) CacheRangeFlush(code, size, CACHE_SYNC_ALL); #elif OS(QNX) @@ -2732,8 +2778,7 @@ private: AssemblerBuffer m_buffer; } m_formatter; - Vector<LinkRecord> m_jumpsToLink; - Vector<int32_t> m_offsets; + Vector<LinkRecord, 0, UnsafeVectorOverflow> m_jumpsToLink; int m_indexOfLastWatchpoint; int m_indexOfTailOfLastWatchpoint; }; diff --git a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h index 673031b7a..1861dc15c 100644 --- a/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h +++ b/Source/JavaScriptCore/assembler/AbstractMacroAssembler.h @@ -31,7 +31,6 @@ #include "MacroAssemblerCodeRef.h" #include <wtf/CryptographicallyRandomNumber.h> #include <wtf/Noncopyable.h> -#include <wtf/UnusedParam.h> #if ENABLE(ASSEMBLER) @@ -46,12 +45,30 @@ namespace JSC { +inline bool isARMv7s() +{ +#if CPU(APPLE_ARMV7S) + return true; +#else + return false; +#endif +} + +inline bool isX86() +{ +#if CPU(X86_64) || CPU(X86) + return true; +#else + return false; +#endif +} + class JumpReplacementWatchpoint; class LinkBuffer; class RepatchBuffer; class Watchpoint; namespace DFG { -class CorrectableJumpPoint; +struct OSRExit; } template <class AssemblerType> @@ -320,7 +337,7 @@ public: class Label { template<class TemplateAssemblerType> friend class AbstractMacroAssembler; - friend class DFG::CorrectableJumpPoint; + friend struct DFG::OSRExit; friend class Jump; friend class JumpReplacementWatchpoint; friend class MacroAssemblerCodeRef; @@ -501,7 +518,7 @@ public: template<class TemplateAssemblerType> friend class AbstractMacroAssembler; friend class Call; - friend class DFG::CorrectableJumpPoint; + friend struct DFG::OSRExit; friend class LinkBuffer; public: Jump() @@ -510,7 +527,7 @@ public: #if CPU(ARM_THUMB2) // Fixme: this information should be stored in the instruction stream, not in the Jump object. - Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid) + Jump(AssemblerLabel jmp, ARMv7Assembler::JumpType type = ARMv7Assembler::JumpNoCondition, ARMv7Assembler::Condition condition = ARMv7Assembler::ConditionInvalid) : m_label(jmp) , m_type(type) , m_condition(condition) @@ -528,9 +545,20 @@ public: { } #endif + + Label label() const + { + Label result; + result.m_label = m_label; + return result; + } void link(AbstractMacroAssembler<AssemblerType>* masm) const { +#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) + masm->checkRegisterAllocationAgainstBranchRange(m_label.m_offset, masm->debugOffset()); +#endif + #if CPU(ARM_THUMB2) masm->m_assembler.linkJump(m_label, masm->m_assembler.label(), m_type, m_condition); #elif CPU(SH4) @@ -542,6 +570,10 @@ public: void linkTo(Label label, AbstractMacroAssembler<AssemblerType>* masm) const { +#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) + masm->checkRegisterAllocationAgainstBranchRange(label.m_label.m_offset, m_label.m_offset); +#endif + #if CPU(ARM_THUMB2) masm->m_assembler.linkJump(m_label, label.m_label, m_type, m_condition); #else @@ -585,7 +617,7 @@ public: friend class LinkBuffer; public: - typedef Vector<Jump, 16> JumpVector; + typedef Vector<Jump, 2> JumpVector; JumpList() { } @@ -676,6 +708,44 @@ public: return Label(this); } +#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) + class RegisterAllocationOffset { + public: + RegisterAllocationOffset(unsigned offset) + : m_offset(offset) + { + } + + void check(unsigned low, unsigned high) + { + RELEASE_ASSERT_WITH_MESSAGE(!(low <= m_offset && m_offset <= high), "Unsafe branch over register allocation at instruction offset %u in jump offset range %u..%u", m_offset, low, high); + } + + private: + unsigned m_offset; + }; + + void addRegisterAllocationAtOffset(unsigned offset) + { + m_registerAllocationForOffsets.append(RegisterAllocationOffset(offset)); + } + + void clearRegisterAllocationOffsets() + { + m_registerAllocationForOffsets.clear(); + } + + void checkRegisterAllocationAgainstBranchRange(unsigned offset1, unsigned offset2) + { + if (offset1 > offset2) + std::swap(offset1, offset2); + + size_t size = m_registerAllocationForOffsets.size(); + for (size_t i = 0; i < size; ++i) + m_registerAllocationForOffsets[i].check(offset1, offset2); + } +#endif + template<typename T, typename U> static ptrdiff_t differenceBetween(T from, U to) { @@ -708,6 +778,10 @@ protected: WeakRandom m_randomSource; +#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) + Vector<RegisterAllocationOffset, 10> m_registerAllocationForOffsets; +#endif + #if ENABLE(JIT_CONSTANT_BLINDING) static bool scratchRegisterForBlinding() { return false; } static bool shouldBlindForSpecificArch(uint32_t) { return true; } diff --git a/Source/JavaScriptCore/assembler/AssemblerBuffer.h b/Source/JavaScriptCore/assembler/AssemblerBuffer.h index 6bc1b3924..d82c0b946 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBuffer.h +++ b/Source/JavaScriptCore/assembler/AssemblerBuffer.h @@ -30,7 +30,7 @@ #include "ExecutableAllocator.h" #include "JITCompilationEffort.h" -#include "JSGlobalData.h" +#include "VM.h" #include "stdint.h" #include <string.h> #include <wtf/Assertions.h> @@ -130,12 +130,12 @@ namespace JSC { return AssemblerLabel(m_index); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { if (!m_index) return 0; - RefPtr<ExecutableMemoryHandle> result = globalData.executableAllocator.allocate(globalData, m_index, ownerUID, effort); + RefPtr<ExecutableMemoryHandle> result = vm.executableAllocator.allocate(vm, m_index, ownerUID, effort); if (!result) return 0; @@ -168,7 +168,7 @@ namespace JSC { } private: - Vector<char, inlineCapacity> m_storage; + Vector<char, inlineCapacity, UnsafeVectorOverflow> m_storage; char* m_buffer; int m_capacity; int m_index; diff --git a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h index 5377ef0c7..852f86df7 100644 --- a/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h +++ b/Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h @@ -195,10 +195,10 @@ public: putIntegralUnchecked(value.low); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { flushConstantPool(false); - return AssemblerBuffer::executableCopy(globalData, ownerUID, effort); + return AssemblerBuffer::executableCopy(vm, ownerUID, effort); } void putShortWithConstantInt(uint16_t insn, uint32_t constant, bool isReusable = false) diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.cpp b/Source/JavaScriptCore/assembler/LinkBuffer.cpp index c269157ba..cd393be65 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.cpp +++ b/Source/JavaScriptCore/assembler/LinkBuffer.cpp @@ -62,7 +62,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort) { ASSERT(!m_code); #if !ENABLE(BRANCH_COMPACTION) - m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort); + m_executableMemory = m_assembler->m_assembler.executableCopy(*m_vm, ownerUID, effort); if (!m_executableMemory) return; m_code = m_executableMemory->start(); @@ -70,7 +70,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort) ASSERT(m_code); #else m_initialSize = m_assembler->m_assembler.codeSize(); - m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort); + m_executableMemory = m_vm->executableAllocator.allocate(*m_vm, m_initialSize, ownerUID, effort); if (!m_executableMemory) return; m_code = (uint8_t*)m_executableMemory->start(); @@ -80,7 +80,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort) uint8_t* outData = reinterpret_cast<uint8_t*>(m_code); int readPtr = 0; int writePtr = 0; - Vector<LinkRecord>& jumpsToLink = m_assembler->jumpsToLink(); + Vector<LinkRecord, 0, UnsafeVectorOverflow>& jumpsToLink = m_assembler->jumpsToLink(); unsigned jumpCount = jumpsToLink.size(); for (unsigned i = 0; i < jumpCount; ++i) { int offset = readPtr - writePtr; diff --git a/Source/JavaScriptCore/assembler/LinkBuffer.h b/Source/JavaScriptCore/assembler/LinkBuffer.h index e1882433c..52630fe50 100644 --- a/Source/JavaScriptCore/assembler/LinkBuffer.h +++ b/Source/JavaScriptCore/assembler/LinkBuffer.h @@ -41,7 +41,7 @@ namespace JSC { -class JSGlobalData; +class VM; // LinkBuffer: // @@ -76,14 +76,14 @@ class LinkBuffer { #endif public: - LinkBuffer(JSGlobalData& globalData, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed) + LinkBuffer(VM& vm, MacroAssembler* masm, void* ownerUID, JITCompilationEffort effort = JITCompilationMustSucceed) : m_size(0) #if ENABLE(BRANCH_COMPACTION) , m_initialSize(0) #endif , m_code(0) , m_assembler(masm) - , m_globalData(&globalData) + , m_vm(&vm) #ifndef NDEBUG , m_completed(false) , m_effort(effort) @@ -256,7 +256,7 @@ private: #endif void* m_code; MacroAssembler* m_assembler; - JSGlobalData* m_globalData; + VM* m_vm; #ifndef NDEBUG bool m_completed; JITCompilationEffort m_effort; diff --git a/Source/JavaScriptCore/assembler/MIPSAssembler.h b/Source/JavaScriptCore/assembler/MIPSAssembler.h index 7f553bb9a..5f7b9b21a 100644 --- a/Source/JavaScriptCore/assembler/MIPSAssembler.h +++ b/Source/JavaScriptCore/assembler/MIPSAssembler.h @@ -676,9 +676,9 @@ public: return m_buffer.codeSize(); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { - RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(globalData, ownerUID, effort); + RefPtr<ExecutableMemoryHandle> result = m_buffer.executableCopy(vm, ownerUID, effort); if (!result) return 0; diff --git a/Source/JavaScriptCore/assembler/MacroAssembler.h b/Source/JavaScriptCore/assembler/MacroAssembler.h index 2f26ff281..f74680d7f 100644 --- a/Source/JavaScriptCore/assembler/MacroAssembler.h +++ b/Source/JavaScriptCore/assembler/MacroAssembler.h @@ -121,7 +121,7 @@ public: case DoubleLessThanOrEqualOrUnordered: return DoubleGreaterThan; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return DoubleEqual; // make compiler happy } } @@ -145,7 +145,7 @@ public: case NonZero: return Zero; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return Zero; // Make compiler happy for release builds. } } @@ -854,7 +854,7 @@ public: bool shouldBlindDouble(double value) { // Don't trust NaN or +/-Infinity - if (!isfinite(value)) + if (!std::isfinite(value)) return shouldConsiderBlinding(); // Try to force normalisation, and check that there's no change @@ -876,7 +876,7 @@ public: bool shouldBlind(ImmPtr imm) { -#if !defined(NDEBUG) +#if ENABLE(FORCED_JIT_BLINDING) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know // if we've broken blinding during patch development. @@ -934,8 +934,8 @@ public: } bool shouldBlind(Imm64 imm) - { -#if !defined(NDEBUG) + { +#if ENABLE(FORCED_JIT_BLINDING) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know // if we've broken blinding during patch development. @@ -1073,8 +1073,8 @@ public: #if ENABLE(JIT_CONSTANT_BLINDING) bool shouldBlind(Imm32 imm) - { -#if !defined(NDEBUG) + { +#if ENABLE(FORCED_JIT_BLINDING) UNUSED_PARAM(imm); // Debug always blind all constants, if only so we know // if we've broken blinding during patch development. @@ -1357,12 +1357,9 @@ public: Jump branchAdd32(ResultCondition cond, RegisterID src, Imm32 imm, RegisterID dest) { - if (src == dest) { - if (!scratchRegisterForBlinding()) { - // Release mode ASSERT, if this fails we will perform incorrect codegen. - CRASH(); - } - } + if (src == dest) + ASSERT(scratchRegisterForBlinding()); + if (shouldBlind(imm)) { if (src == dest) { if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { @@ -1378,12 +1375,9 @@ public: Jump branchMul32(ResultCondition cond, Imm32 imm, RegisterID src, RegisterID dest) { - if (src == dest) { - if (!scratchRegisterForBlinding()) { - // Release mode ASSERT, if this fails we will perform incorrect codegen. - CRASH(); - } - } + if (src == dest) + ASSERT(scratchRegisterForBlinding()); + if (shouldBlind(imm)) { if (src == dest) { if (RegisterID scratchRegister = (RegisterID)scratchRegisterForBlinding()) { diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h index c5ea9c542..494fe640d 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARM.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARM.h @@ -58,6 +58,7 @@ public: enum ResultCondition { Overflow = ARMAssembler::VS, Signed = ARMAssembler::MI, + PositiveOrZero = ARMAssembler::PL, Zero = ARMAssembler::EQ, NonZero = ARMAssembler::NE }; @@ -152,6 +153,12 @@ public: m_assembler.bitAnds(dest, src, w); } + void and32(Address src, RegisterID dest) + { + load32(src, ARMRegisters::S1); + and32(ARMRegisters::S1, dest); + } + void lshift32(RegisterID shiftAmount, RegisterID dest) { lshift32(dest, shiftAmount, dest); @@ -342,7 +349,7 @@ public: #else UNUSED_PARAM(src); UNUSED_PARAM(dest); - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); #endif } @@ -445,10 +452,10 @@ public: m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint8, src, address.base, address.index, static_cast<int>(address.scale), address.offset); } - void store8(TrustedImm32 imm, void* address) + void store8(TrustedImm32 imm, const void* address) { move(TrustedImm32(reinterpret_cast<ARMWord>(address)), ARMRegisters::S0); - m_assembler.moveImm(imm.m_value, ARMRegisters::S1); + move(imm, ARMRegisters::S1); m_assembler.dtrUp(ARMAssembler::StoreUint8, ARMRegisters::S1, ARMRegisters::S0, 0); } @@ -479,13 +486,13 @@ public: m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint32, ARMRegisters::S1, address.base, address.index, static_cast<int>(address.scale), address.offset); } - void store32(RegisterID src, void* address) + void store32(RegisterID src, const void* address) { m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); m_assembler.dtrUp(ARMAssembler::StoreUint32, src, ARMRegisters::S0, 0); } - void store32(TrustedImm32 imm, void* address) + void store32(TrustedImm32 imm, const void* address) { m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address)); m_assembler.moveImm(imm.m_value, ARMRegisters::S1); @@ -532,9 +539,9 @@ public: void swap(RegisterID reg1, RegisterID reg2) { - m_assembler.mov(ARMRegisters::S0, reg1); - m_assembler.mov(reg1, reg2); - m_assembler.mov(reg2, ARMRegisters::S0); + xor32(reg1, reg2); + xor32(reg2, reg1); + xor32(reg1, reg2); } void signExtend32ToPtr(RegisterID src, RegisterID dest) @@ -680,35 +687,40 @@ public: Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) + || (cond == NonZero) || (cond == PositiveOrZero)); add32(src, dest); return Jump(m_assembler.jmp(ARMCondition(cond))); } Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) + || (cond == NonZero) || (cond == PositiveOrZero)); add32(op1, op2, dest); return Jump(m_assembler.jmp(ARMCondition(cond))); } Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) + || (cond == NonZero) || (cond == PositiveOrZero)); add32(imm, dest); return Jump(m_assembler.jmp(ARMCondition(cond))); } Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) + || (cond == NonZero) || (cond == PositiveOrZero)); add32(src, imm, dest); return Jump(m_assembler.jmp(ARMCondition(cond))); } Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) + || (cond == NonZero) || (cond == PositiveOrZero)); add32(imm, dest); return Jump(m_assembler.jmp(ARMCondition(cond))); } @@ -885,20 +897,41 @@ public: void add32(TrustedImm32 imm, AbsoluteAddress address) { - m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr)); - m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0); + load32(address.m_ptr, ARMRegisters::S1); add32(imm, ARMRegisters::S1); - m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr)); - m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0); + store32(ARMRegisters::S1, address.m_ptr); + } + + void add64(TrustedImm32 imm, AbsoluteAddress address) + { + ARMWord tmp; + + move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1); + m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S0, ARMRegisters::S1, 0); + + if ((tmp = ARMAssembler::getOp2(imm.m_value)) != ARMAssembler::InvalidImmediate) + m_assembler.adds(ARMRegisters::S0, ARMRegisters::S0, tmp); + else if ((tmp = ARMAssembler::getOp2(-imm.m_value)) != ARMAssembler::InvalidImmediate) + m_assembler.subs(ARMRegisters::S0, ARMRegisters::S0, tmp); + else { + m_assembler.adds(ARMRegisters::S0, ARMRegisters::S0, m_assembler.getImm(imm.m_value, ARMRegisters::S1)); + move(TrustedImmPtr(address.m_ptr), ARMRegisters::S1); + } + m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S0, ARMRegisters::S1, 0); + + m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S0, ARMRegisters::S1, sizeof(ARMWord)); + if (imm.m_value >= 0) + m_assembler.adc(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(0)); + else + m_assembler.sbc(ARMRegisters::S0, ARMRegisters::S0, ARMAssembler::getOp2Byte(0)); + m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S0, ARMRegisters::S1, sizeof(ARMWord)); } void sub32(TrustedImm32 imm, AbsoluteAddress address) { - m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast<ARMWord>(address.m_ptr)); - m_assembler.dtrUp(ARMAssembler::LoadUint32, ARMRegisters::S1, ARMRegisters::S1, 0); + load32(address.m_ptr, ARMRegisters::S1); sub32(imm, ARMRegisters::S1); - m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast<ARMWord>(address.m_ptr)); - m_assembler.dtrUp(ARMAssembler::StoreUint32, ARMRegisters::S1, ARMRegisters::S0, 0); + store32(ARMRegisters::S1, address.m_ptr); } void load32(const void* address, RegisterID dest) @@ -1080,7 +1113,7 @@ public: void divDouble(Address src, FPRegisterID dest) { - ASSERT_NOT_REACHED(); // Untested + RELEASE_ASSERT_NOT_REACHED(); // Untested loadDouble(src, ARMRegisters::SD0); divDouble(ARMRegisters::SD0, dest); } @@ -1216,7 +1249,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_s32_f64(ARMRegisters::SD0 << 1, src); m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1); @@ -1226,7 +1259,8 @@ public: failureCases.append(branchDouble(DoubleNotEqualOrUnordered, src, ARMRegisters::SD0)); // If the result is zero, it might have been -0.0, and 0.0 equals to -0.0 - failureCases.append(branchTest32(Zero, dest)); + if (negZeroCheck) + failureCases.append(branchTest32(Zero, dest)); } Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h index 06d0e1534..b1bc41729 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h @@ -59,7 +59,7 @@ public: return value >= -255 && value <= 255; } - Vector<LinkRecord>& jumpsToLink() { return m_assembler.jumpsToLink(); } + Vector<LinkRecord, 0, UnsafeVectorOverflow>& 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); } @@ -119,6 +119,7 @@ public: enum ResultCondition { Overflow = ARMv7Assembler::ConditionVS, Signed = ARMv7Assembler::ConditionMI, + PositiveOrZero = ARMv7Assembler::ConditionPL, Zero = ARMv7Assembler::ConditionEQ, NonZero = ARMv7Assembler::ConditionNE }; @@ -263,6 +264,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); @@ -1097,7 +1104,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()); @@ -1107,7 +1114,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) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h index c2af24060..ec16659d5 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h @@ -32,7 +32,6 @@ #include <wtf/DataLog.h> #include <wtf/PassRefPtr.h> #include <wtf/RefPtr.h> -#include <wtf/UnusedParam.h> // ASSERT_VALID_CODE_POINTER checks that ptr is a non-null pointer, and that it is a valid // instruction address on the platform (for example, check any alignment requirements). diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h index f5298a0ab..298a25c29 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h @@ -80,6 +80,7 @@ public: enum ResultCondition { Overflow, Signed, + PositiveOrZero, Zero, NonZero }; @@ -233,22 +234,46 @@ 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_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); @@ -596,7 +621,7 @@ public: void absDouble(FPRegisterID, FPRegisterID) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) @@ -1485,7 +1510,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 @@ -1518,6 +1543,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); @@ -1532,7 +1563,7 @@ public: Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, 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 dataTemp, op1 @@ -1565,6 +1596,12 @@ public: 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); @@ -1592,7 +1629,7 @@ public: Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress 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 dataTemp, dest @@ -1642,6 +1679,11 @@ public: 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) @@ -2598,13 +2640,14 @@ 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 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); diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp deleted file mode 100644 index 59de3ff48..000000000 --- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2011 STMicroelectronics. All rights reserved. - * Copyright (C) 2008 Apple Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR - * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -#include "config.h" - -#if ENABLE(ASSEMBLER) && CPU(SH4) - -#include "MacroAssemblerSH4.h" - -namespace JSC { - -void MacroAssemblerSH4::linkCall(void* code, Call call, FunctionPtr function) -{ - SH4Assembler::linkCall(code, call.m_label, function.value()); -} - -void MacroAssemblerSH4::repatchCall(CodeLocationCall call, CodeLocationLabel destination) -{ - SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); -} - -void MacroAssemblerSH4::repatchCall(CodeLocationCall call, FunctionPtr destination) -{ - SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); -} - -} // namespace JSC - -#endif // ENABLE(ASSEMBLER) diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h index 0c7fe12c6..ad5acfaeb 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerSH4.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved. * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. * Copyright (C) 2008 Apple Inc. All rights reserved. * @@ -40,7 +41,7 @@ public: typedef SH4Assembler::FPRegisterID FPRegisterID; static const Scale ScalePtr = TimesFour; - static const FPRegisterID fscratch = SH4Registers::fr10; + static const FPRegisterID fscratch = SH4Registers::dr10; static const RegisterID stackPointerRegister = SH4Registers::sp; static const RegisterID linkRegister = SH4Registers::pr; static const RegisterID scratchReg3 = SH4Registers::r13; @@ -49,7 +50,7 @@ public: static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value) { - return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset); + return (value >= 0) && (value <= MaximumCompactPtrAlignedAddressOffset) && (!(value & 3)); } enum RelationalCondition { @@ -68,6 +69,7 @@ public: enum ResultCondition { Overflow = SH4Assembler::OF, Signed = SH4Assembler::SI, + PositiveOrZero = SH4Assembler::NS, Zero = SH4Assembler::EQ, NonZero = SH4Assembler::NE }; @@ -99,6 +101,34 @@ public: m_assembler.releaseScratch(reg); } + static RelationalCondition invert(RelationalCondition cond) + { + switch (cond) { + case Equal: + return NotEqual; + case NotEqual: + return Equal; + case Above: + return BelowOrEqual; + case AboveOrEqual: + return Below; + case Below: + return AboveOrEqual; + case BelowOrEqual: + return Above; + case GreaterThan: + return LessThanOrEqual; + case GreaterThanOrEqual: + return LessThan; + case LessThan: + return GreaterThanOrEqual; + case LessThanOrEqual: + return GreaterThan; + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + // Integer arithmetic operations void add32(RegisterID src, RegisterID dest) @@ -106,8 +136,21 @@ public: m_assembler.addlRegReg(src, dest); } + void add32(RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 == dest) + add32(src2, dest); + else { + move(src2, dest); + add32(src1, dest); + } + } + void add32(TrustedImm32 imm, RegisterID dest) { + if (!imm.m_value) + return; + if (m_assembler.isImmediate(imm.m_value)) { m_assembler.addlImm8r(imm.m_value, dest); return; @@ -121,13 +164,15 @@ public: void add32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (src != dest) - m_assembler.movlRegReg(src, dest); + move(src, dest); add32(imm, dest); } void add32(TrustedImm32 imm, Address address) { + if (!imm.m_value) + return; + RegisterID scr = claimScratch(); load32(address, scr); add32(imm, scr); @@ -156,15 +201,38 @@ public: m_assembler.andlRegReg(src, dest); } + void and32(RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 == dest) + and32(src2, dest); + else { + move(src2, dest); + and32(src1, dest); + } + } + + void and32(Address src, RegisterID dest) + { + RegisterID scr = claimScratch(); + load32(src, scr); + and32(scr, dest); + releaseScratch(scr); + } + void and32(TrustedImm32 imm, RegisterID dest) { + if (!imm.m_value) { + m_assembler.movImm8(0, dest); + return; + } + if ((imm.m_value <= 255) && (imm.m_value >= 0) && (dest == SH4Registers::r0)) { m_assembler.andlImm8r(imm.m_value, dest); return; } RegisterID scr = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); + m_assembler.loadConstant(imm.m_value, scr); m_assembler.andlRegReg(scr, dest); releaseScratch(scr); } @@ -182,63 +250,64 @@ public: void lshift32(RegisterID shiftamount, RegisterID dest) { - if (shiftamount == SH4Registers::r0) - m_assembler.andlImm8r(0x1f, shiftamount); - else { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x1f, scr); - m_assembler.andlRegReg(scr, shiftamount); - releaseScratch(scr); - } - m_assembler.shllRegReg(dest, shiftamount); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } - void rshift32(int imm, RegisterID dest) + void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(-imm, scr); - m_assembler.shaRegReg(dest, scr); - releaseScratch(scr); + move(src, dest); + lshift32(shiftAmount, dest); } void lshift32(TrustedImm32 imm, RegisterID dest) { - if (!imm.m_value) + int immMasked = imm.m_value & 0x1f; + if (!immMasked) return; - if ((imm.m_value == 1) || (imm.m_value == 2) || (imm.m_value == 8) || (imm.m_value == 16)) { - m_assembler.shllImm8r(imm.m_value, dest); + if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { + m_assembler.shllImm8r(immMasked, dest); return; } - RegisterID scr = claimScratch(); - m_assembler.loadConstant((imm.m_value & 0x1f) , scr); - m_assembler.shllRegReg(dest, scr); - releaseScratch(scr); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(immMasked, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } void lshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) { - if (src != dest) - move(src, dest); - + move(src, dest); lshift32(shiftamount, dest); } void mul32(RegisterID src, RegisterID dest) { - m_assembler.imullRegReg(src, dest); + mul32(src, dest, dest); + } + + void mul32(RegisterID src1, RegisterID src2, RegisterID dest) + { + m_assembler.imullRegReg(src1, src2); m_assembler.stsmacl(dest); } void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - RegisterID scr = claimScratch(); - move(imm, scr); - if (src != dest) - move(src, dest); - mul32(scr, dest); - releaseScratch(scr); + if (src == dest) { + RegisterID immval = claimScratch(); + move(imm, immval); + mul32(immval, dest); + releaseScratch(immval); + } else { + move(imm, dest); + mul32(src, dest); + } } void or32(RegisterID src, RegisterID dest) @@ -271,10 +340,9 @@ public: } } - -void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (src != dest) { + if (src != dest) { move(imm, dest); or32(src, dest); return; @@ -283,9 +351,21 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) or32(imm, dest); } + void or32(RegisterID src, AbsoluteAddress address) + { + RegisterID destptr = claimScratch(); + move(TrustedImmPtr(address.m_ptr), destptr); + RegisterID destval = claimScratch(); + m_assembler.movlMemReg(destptr, destval); + m_assembler.orlRegReg(src, destval); + m_assembler.movlRegMem(destval, destptr); + releaseScratch(destval); + releaseScratch(destptr); + } + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - if (src != dest) { + if (src != dest) { move(imm, dest); xor32(src, dest); return; @@ -296,28 +376,40 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void rshift32(RegisterID shiftamount, RegisterID dest) { - if (shiftamount == SH4Registers::r0) - m_assembler.andlImm8r(0x1f, shiftamount); - else { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x1f, scr); - m_assembler.andlRegReg(scr, shiftamount); - releaseScratch(scr); - } - m_assembler.neg(shiftamount, shiftamount); - m_assembler.shaRegReg(dest, shiftamount); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.neg(shiftTmp, shiftTmp); + m_assembler.shadRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); + } + + void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + move(src, dest); + rshift32(shiftAmount, dest); } void rshift32(TrustedImm32 imm, RegisterID dest) { - if (imm.m_value & 0x1f) - rshift32(imm.m_value & 0x1f, dest); + int immMasked = imm.m_value & 0x1f; + if (!immMasked) + return; + + if (immMasked == 1) { + m_assembler.sharImm8r(immMasked, dest); + return; + } + + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(-immMasked, shiftTmp); + m_assembler.shadRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } void rshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) { - if (src != dest) - move(src, dest); + move(src, dest); rshift32(imm, dest); } @@ -326,30 +418,15 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.sublRegReg(src, dest); } - void sub32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) - { - RegisterID result = claimScratch(); - - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); - m_assembler.movlMemReg(scratchReg, result); - - if (m_assembler.isImmediate(-imm.m_value)) - m_assembler.addlImm8r(-imm.m_value, result); - else { - m_assembler.loadConstant(imm.m_value, scratchReg3); - m_assembler.sublRegReg(scratchReg3, result); - } - - store32(result, scratchReg); - releaseScratch(result); - } - void sub32(TrustedImm32 imm, AbsoluteAddress address) { + if (!imm.m_value) + return; + RegisterID result = claimScratch(); RegisterID scratchReg = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); + move(TrustedImmPtr(address.m_ptr), scratchReg); m_assembler.movlMemReg(scratchReg, result); if (m_assembler.isImmediate(-imm.m_value)) @@ -364,30 +441,20 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) releaseScratch(scratchReg); } - void add32(TrustedImm32 imm, AbsoluteAddress address, RegisterID scratchReg) + void sub32(TrustedImm32 imm, Address address) { - RegisterID result = claimScratch(); - - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); - m_assembler.movlMemReg(scratchReg, result); - - if (m_assembler.isImmediate(imm.m_value)) - m_assembler.addlImm8r(imm.m_value, result); - else { - m_assembler.loadConstant(imm.m_value, scratchReg3); - m_assembler.addlRegReg(scratchReg3, result); - } - - store32(result, scratchReg); - releaseScratch(result); + add32(TrustedImm32(-imm.m_value), address); } void add32(TrustedImm32 imm, AbsoluteAddress address) { + if (!imm.m_value) + return; + RegisterID result = claimScratch(); RegisterID scratchReg = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address.m_ptr), scratchReg); + move(TrustedImmPtr(address.m_ptr), scratchReg); m_assembler.movlMemReg(scratchReg, result); if (m_assembler.isImmediate(imm.m_value)) @@ -402,8 +469,37 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) releaseScratch(scratchReg); } + void add64(TrustedImm32 imm, AbsoluteAddress address) + { + RegisterID scr1 = claimScratch(); + RegisterID scr2 = claimScratch(); + + // Add 32-bit LSB first. + move(TrustedImmPtr(address.m_ptr), scratchReg3); + m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit LSB of int64 @ address + m_assembler.loadConstant(imm.m_value, scr2); + m_assembler.clrt(); + m_assembler.addclRegReg(scr1, scr2); + m_assembler.movlRegMem(scr2, scratchReg3); // Update address with 32-bit LSB result. + + // Then add 32-bit MSB. + m_assembler.addlImm8r(4, scratchReg3); + m_assembler.movlMemReg(scratchReg3, scr1); // scr1 = 32-bit MSB of int64 @ address + m_assembler.movt(scr2); + if (imm.m_value < 0) + m_assembler.addlImm8r(-1, scr2); // Sign extend imm value if needed. + m_assembler.addvlRegReg(scr2, scr1); + m_assembler.movlRegMem(scr1, scratchReg3); // Update (address + 4) with 32-bit MSB result. + + releaseScratch(scr2); + releaseScratch(scr1); + } + void sub32(TrustedImm32 imm, RegisterID dest) { + if (!imm.m_value) + return; + if (m_assembler.isImmediate(-imm.m_value)) { m_assembler.addlImm8r(-imm.m_value, dest); return; @@ -428,6 +524,16 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.xorlRegReg(src, dest); } + void xor32(RegisterID src1, RegisterID src2, RegisterID dest) + { + if (src1 == dest) + xor32(src2, dest); + else { + move(src2, dest); + xor32(src1, dest); + } + } + void xor32(TrustedImm32 imm, RegisterID srcDest) { if (imm.m_value == -1) { @@ -437,7 +543,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) if ((srcDest != SH4Registers::r0) || (imm.m_value > 255) || (imm.m_value < 0)) { RegisterID scr = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); + m_assembler.loadConstant(imm.m_value, scr); m_assembler.xorlRegReg(scr, srcDest); releaseScratch(scr); return; @@ -453,6 +559,11 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) return; } + if (((cond == Equal) || (cond == NotEqual)) && !imm) { + m_assembler.testlRegReg(dst, dst); + return; + } + RegisterID scr = claimScratch(); m_assembler.loadConstant(imm, scr); m_assembler.cmplRegReg(scr, dst, SH4Condition(cond)); @@ -486,20 +597,10 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void testImm(int imm, int offset, RegisterID base) { RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); + load32(base, offset, scr); - if ((offset < 0) || (offset >= 64)) { - m_assembler.loadConstant(offset, scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movlMemReg(scr, scr); - } else if (offset) - m_assembler.movlMemReg(offset >> 2, base, scr); - else - m_assembler.movlMemReg(base, scr); - if (m_assembler.isImmediate(imm)) - m_assembler.movImm8(imm, scr1); - else - m_assembler.loadConstant(imm, scr1); + RegisterID scr1 = claimScratch(); + move(TrustedImm32(imm), scr1); m_assembler.testlRegReg(scr, scr1); releaseScratch(scr); @@ -547,41 +648,37 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void compare32(int imm, int offset, RegisterID base, RelationalCondition cond) { - if (!offset) { - RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); - m_assembler.movlMemReg(base, scr); - m_assembler.loadConstant(imm, scr1); - m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); - releaseScratch(scr1); - releaseScratch(scr); - return; - } - - if ((offset < 0) || (offset >= 64)) { - RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); - m_assembler.loadConstant(offset, scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movlMemReg(scr, scr); - m_assembler.loadConstant(imm, scr1); - m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); - releaseScratch(scr1); - releaseScratch(scr); - return; - } - RegisterID scr = claimScratch(); + load32(base, offset, scr); + RegisterID scr1 = claimScratch(); - m_assembler.movlMemReg(offset >> 2, base, scr); - m_assembler.loadConstant(imm, scr1); + move(TrustedImm32(imm), scr1); + m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); + releaseScratch(scr1); releaseScratch(scr); } // Memory access operation + ALWAYS_INLINE void loadEffectiveAddress(BaseIndex address, RegisterID dest, int extraoffset = 0) + { + if (dest == address.base) { + RegisterID scaledIndex = claimScratch(); + move(address.index, scaledIndex); + lshift32(TrustedImm32(address.scale), scaledIndex); + add32(scaledIndex, dest); + releaseScratch(scaledIndex); + } else { + move(address.index, dest); + lshift32(TrustedImm32(address.scale), dest); + add32(address.base, dest); + } + + add32(TrustedImm32(address.offset + extraoffset), dest); + } + void load32(ImplicitAddress address, RegisterID dest) { load32(address.base, address.offset, dest); @@ -602,6 +699,12 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) releaseScratch(scr); } + void load8PostInc(RegisterID base, RegisterID dest) + { + m_assembler.movbMemRegIn(base, dest); + m_assembler.extub(dest, dest); + } + void load8Signed(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); @@ -624,7 +727,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void load32(const void* address, RegisterID dest) { - m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)), dest); + move(TrustedImmPtr(address), dest); m_assembler.movlMemReg(dest, dest); } @@ -640,20 +743,15 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) return; } - if ((dest == SH4Registers::r0) && (dest != base)) { - m_assembler.loadConstant((offset), dest); - m_assembler.movlR0mr(base, dest); - return; - } + RegisterID scr = (dest == base) ? claimScratch() : dest; - RegisterID scr; - if (dest == base) - scr = claimScratch(); - else - scr = dest; - m_assembler.loadConstant((offset), scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movlMemReg(scr, dest); + m_assembler.loadConstant(offset, scr); + if (base == SH4Registers::r0) + m_assembler.movlR0mr(scr, dest); + else { + m_assembler.addlRegReg(base, scr); + m_assembler.movlMemReg(scr, dest); + } if (dest == base) releaseScratch(scr); @@ -666,59 +764,29 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) return; } - if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) { + if ((offset > 0) && (offset <= 15) && (dest == SH4Registers::r0)) { m_assembler.movbMemReg(offset, base, dest); return; } - if (base != dest) { - m_assembler.loadConstant((offset), dest); - m_assembler.addlRegReg(base, dest); - m_assembler.movbMemReg(dest, dest); - return; + RegisterID scr = (dest == base) ? claimScratch() : dest; + + m_assembler.loadConstant(offset, scr); + if (base == SH4Registers::r0) + m_assembler.movbR0mr(scr, dest); + else { + m_assembler.addlRegReg(base, scr); + m_assembler.movbMemReg(scr, dest); } - RegisterID scr = claimScratch(); - m_assembler.loadConstant((offset), scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movbMemReg(scr, dest); - releaseScratch(scr); + if (dest == base) + releaseScratch(scr); } void load8(RegisterID base, int offset, RegisterID dest) { - if (!offset) { - m_assembler.movbMemReg(base, dest); - m_assembler.extub(dest, dest); - return; - } - - if ((offset > 0) && (offset < 64) && (dest == SH4Registers::r0)) { - m_assembler.movbMemReg(offset, base, dest); - m_assembler.extub(dest, dest); - return; - } - - if (base != dest) { - m_assembler.loadConstant((offset), dest); - m_assembler.addlRegReg(base, dest); - m_assembler.movbMemReg(dest, dest); - m_assembler.extub(dest, dest); - return; - } - - RegisterID scr = claimScratch(); - m_assembler.loadConstant((offset), scr); - m_assembler.addlRegReg(base, scr); - m_assembler.movbMemReg(scr, dest); + load8Signed(base, offset, dest); m_assembler.extub(dest, dest); - releaseScratch(scr); - } - - void load32(RegisterID r0, RegisterID src, RegisterID dst) - { - ASSERT(r0 == SH4Registers::r0); - m_assembler.movlR0mr(src, dst); } void load32(RegisterID src, RegisterID dst) @@ -730,47 +798,39 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { if (!address.offset) { m_assembler.movwMemReg(address.base, dest); - extuw(dest, dest); + m_assembler.extuw(dest, dest); return; } - if ((address.offset > 0) && (address.offset < 64) && (dest == SH4Registers::r0)) { - m_assembler.movwMemReg(address.offset, address.base, dest); - extuw(dest, dest); + if ((address.offset > 0) && (address.offset <= 30) && (dest == SH4Registers::r0)) { + m_assembler.movwMemReg(address.offset >> 1, address.base, dest); + m_assembler.extuw(dest, dest); return; } - if (address.base != dest) { - m_assembler.loadConstant((address.offset), dest); - m_assembler.addlRegReg(address.base, dest); - m_assembler.movwMemReg(dest, dest); - extuw(dest, dest); - return; + RegisterID scr = (dest == address.base) ? claimScratch() : dest; + + m_assembler.loadConstant(address.offset, scr); + if (address.base == SH4Registers::r0) + m_assembler.movwR0mr(scr, dest); + else { + m_assembler.addlRegReg(address.base, scr); + m_assembler.movwMemReg(scr, dest); } + m_assembler.extuw(dest, dest); - RegisterID scr = claimScratch(); - m_assembler.loadConstant((address.offset), scr); - m_assembler.addlRegReg(address.base, scr); - m_assembler.movwMemReg(scr, dest); - extuw(dest, dest); - releaseScratch(scr); + if (dest == address.base) + releaseScratch(scr); } void load16Unaligned(BaseIndex address, RegisterID dest) { - RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); - - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); + loadEffectiveAddress(address, scr); - add32(address.base, scr); - load8(scr, scr1); - add32(TrustedImm32(1), scr); + RegisterID scr1 = claimScratch(); + load8PostInc(scr, scr1); load8(scr, dest); m_assembler.shllImm8r(8, dest); or32(scr1, dest); @@ -782,7 +842,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void load16(RegisterID src, RegisterID dest) { m_assembler.movwMemReg(src, dest); - extuw(dest, dest); + m_assembler.extuw(dest, dest); } void load16Signed(RegisterID src, RegisterID dest) @@ -790,68 +850,63 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.movwMemReg(src, dest); } - void load16(RegisterID r0, RegisterID src, RegisterID dest) + void load16(BaseIndex address, RegisterID dest) { - ASSERT(r0 == SH4Registers::r0); - m_assembler.movwR0mr(src, dest); - extuw(dest, dest); + load16Signed(address, dest); + m_assembler.extuw(dest, dest); } - void load16Signed(RegisterID r0, RegisterID src, RegisterID dest) + void load16PostInc(RegisterID base, RegisterID dest) { - ASSERT(r0 == SH4Registers::r0); - m_assembler.movwR0mr(src, dest); + m_assembler.movwMemRegIn(base, dest); + m_assembler.extuw(dest, dest); } - void load16(BaseIndex address, RegisterID dest) + void load16Signed(BaseIndex address, RegisterID dest) { RegisterID scr = claimScratch(); move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); + add32(TrustedImm32(address.offset), scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); if (address.base == SH4Registers::r0) - load16(address.base, scr, dest); + m_assembler.movwR0mr(scr, dest); else { add32(address.base, scr); - load16(scr, dest); + load16Signed(scr, dest); } releaseScratch(scr); } - void load16Signed(BaseIndex address, RegisterID dest) + void store8(RegisterID src, BaseIndex address) { RegisterID scr = claimScratch(); move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); + add32(TrustedImm32(address.offset), scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); if (address.base == SH4Registers::r0) - load16Signed(address.base, scr, dest); + m_assembler.movbRegMemr0(src, scr); else { add32(address.base, scr); - load16Signed(scr, dest); + m_assembler.movbRegMem(src, scr); } releaseScratch(scr); } - void store8(RegisterID src, BaseIndex address) + void store8(TrustedImm32 imm, void* address) { - RegisterID scr = claimScratch(); - - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - - m_assembler.movbRegMem(src, scr); - - releaseScratch(scr); + RegisterID srcval = claimScratch(); + RegisterID dstptr = claimScratch(); + move(imm, srcval); + m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), dstptr); + m_assembler.movbRegMem(srcval, dstptr); + releaseScratch(dstptr); + releaseScratch(srcval); } void store16(RegisterID src, BaseIndex address) @@ -860,46 +915,39 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) move(address.index, scr); lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); + add32(TrustedImm32(address.offset), scr); - m_assembler.movwRegMem(src, scr); + if (address.base == SH4Registers::r0) + m_assembler.movwRegMemr0(src, scr); + else { + add32(address.base, scr); + m_assembler.movwRegMem(src, scr); + } releaseScratch(scr); } void store32(RegisterID src, ImplicitAddress address) { - RegisterID scr = claimScratch(); - store32(src, address.offset, address.base, scr); - releaseScratch(scr); - } - - void store32(RegisterID src, int offset, RegisterID base, RegisterID scr) - { - if (!offset) { - m_assembler.movlRegMem(src, base); + if (!address.offset) { + m_assembler.movlRegMem(src, address.base); return; } - if ((offset >=0) && (offset < 64)) { - m_assembler.movlRegMem(src, offset >> 2, base); + if ((address.offset >= 0) && (address.offset < 64)) { + m_assembler.movlRegMem(src, address.offset >> 2, address.base); return; } - m_assembler.loadConstant((offset), scr); - if (scr == SH4Registers::r0) { - m_assembler.movlRegMemr0(src, base); - return; + RegisterID scr = claimScratch(); + m_assembler.loadConstant(address.offset, scr); + if (address.base == SH4Registers::r0) + m_assembler.movlRegMemr0(src, scr); + else { + m_assembler.addlRegReg(address.base, scr); + m_assembler.movlRegMem(src, scr); } - - m_assembler.addlRegReg(base, scr); - m_assembler.movlRegMem(src, scr); - } - - void store32(RegisterID src, RegisterID offset, RegisterID base) - { - ASSERT(offset == SH4Registers::r0); - m_assembler.movlRegMemr0(src, base); + releaseScratch(scr); } void store32(RegisterID src, RegisterID dst) @@ -910,11 +958,9 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void store32(TrustedImm32 imm, ImplicitAddress address) { RegisterID scr = claimScratch(); - RegisterID scr1 = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); - store32(scr, address.offset, address.base, scr1); + m_assembler.loadConstant(imm.m_value, scr); + store32(scr, address); releaseScratch(scr); - releaseScratch(scr1); } void store32(RegisterID src, BaseIndex address) @@ -933,8 +979,8 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID scr = claimScratch(); RegisterID scr1 = claimScratch(); - m_assembler.loadConstant((imm.m_value), scr); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr1); + m_assembler.loadConstant(imm.m_value, scr); + move(TrustedImmPtr(address), scr1); m_assembler.movlRegMem(scr, scr1); releaseScratch(scr); releaseScratch(scr1); @@ -943,11 +989,24 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void store32(RegisterID src, void* address) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr); + move(TrustedImmPtr(address), scr); m_assembler.movlRegMem(src, scr); releaseScratch(scr); } + void store32(TrustedImm32 imm, BaseIndex address) + { + RegisterID destptr = claimScratch(); + + loadEffectiveAddress(address, destptr); + + RegisterID srcval = claimScratch(); + move(imm, srcval); + m_assembler.movlRegMem(srcval, destptr); + releaseScratch(srcval); + releaseScratch(destptr); + } + DataLabel32 load32WithAddressOffsetPatch(Address address, RegisterID dest) { RegisterID scr = claimScratch(); @@ -973,8 +1032,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) DataLabelCompact load32WithCompactAddressOffsetPatch(Address address, RegisterID dest) { DataLabelCompact dataLabel(this); - ASSERT(address.offset <= MaximumCompactPtrAlignedAddressOffset); - ASSERT(address.offset >= 0); + ASSERT(isCompactPtrAlignedAddressOffset(address.offset)); m_assembler.movlMemRegCompact(address.offset >> 2, address.base, dest); return dataLabel; } @@ -997,7 +1055,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) static bool supportsFloatingPoint() { return true; } static bool supportsFloatingPointTruncate() { return true; } static bool supportsFloatingPointSqrt() { return true; } - static bool supportsFloatingPointAbs() { return false; } + static bool supportsFloatingPointAbs() { return true; } void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) { @@ -1007,24 +1065,39 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.stsfpulReg(dest2); } - void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch) + void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID) { - UNUSED_PARAM(scratch); m_assembler.ldsrmfpul(src1); m_assembler.fstsfpul((FPRegisterID)(dest + 1)); m_assembler.ldsrmfpul(src2); m_assembler.fstsfpul(dest); } + void moveDouble(FPRegisterID src, FPRegisterID dest) + { + if (src != dest) { + m_assembler.fmovsRegReg((FPRegisterID)(src + 1), (FPRegisterID)(dest + 1)); + m_assembler.fmovsRegReg(src, dest); + } + } + + void swapDouble(FPRegisterID fr1, FPRegisterID fr2) + { + if (fr1 != fr2) { + m_assembler.fldsfpul((FPRegisterID)(fr1 + 1)); + m_assembler.fmovsRegReg((FPRegisterID)(fr2 + 1), (FPRegisterID)(fr1 + 1)); + m_assembler.fstsfpul((FPRegisterID)(fr2 + 1)); + m_assembler.fldsfpul(fr1); + m_assembler.fmovsRegReg(fr2, fr1); + m_assembler.fstsfpul(fr2); + } + } + void loadFloat(BaseIndex address, FPRegisterID dest) { RegisterID scr = claimScratch(); - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); + loadEffectiveAddress(address, scr); m_assembler.fmovsReadrm(scr, dest); releaseScratch(scr); @@ -1034,11 +1107,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID scr = claimScratch(); - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); + loadEffectiveAddress(address, scr); m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); m_assembler.fmovsReadrm(scr, dest); @@ -1067,7 +1136,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void loadDouble(const void* address, FPRegisterID dest) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(address), scr); + move(TrustedImmPtr(address), scr); m_assembler.fmovsReadrminc(scr, (FPRegisterID)(dest + 1)); m_assembler.fmovsReadrm(scr, dest); releaseScratch(scr); @@ -1076,26 +1145,18 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void storeFloat(FPRegisterID src, BaseIndex address) { RegisterID scr = claimScratch(); - - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); - + loadEffectiveAddress(address, scr); m_assembler.fmovsWriterm(src, scr); - releaseScratch(scr); } void storeDouble(FPRegisterID src, ImplicitAddress address) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(address.offset, scr); + m_assembler.loadConstant(address.offset + 8, scr); m_assembler.addlRegReg(address.base, scr); - m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr); - m_assembler.addlImm8r(4, scr); - m_assembler.fmovsWriterm(src, scr); + m_assembler.fmovsWriterndec(src, scr); + m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); releaseScratch(scr); } @@ -1103,15 +1164,10 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID scr = claimScratch(); - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - if (address.offset) - add32(TrustedImm32(address.offset), scr); + loadEffectiveAddress(address, scr, 8); - m_assembler.fmovsWriterm((FPRegisterID)(src + 1), scr); - m_assembler.addlImm8r(4, scr); - m_assembler.fmovsWriterm(src, scr); + m_assembler.fmovsWriterndec(src, scr); + m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); releaseScratch(scr); } @@ -1119,13 +1175,22 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void addDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) { if (op1 == dest) - m_assembler.daddRegReg(op2, dest); + addDouble(op2, dest); else { - m_assembler.dmovRegReg(op1, dest); - m_assembler.daddRegReg(op2, dest); + moveDouble(op2, dest); + addDouble(op1, dest); } } + void storeDouble(FPRegisterID src, const void* address) + { + RegisterID scr = claimScratch(); + m_assembler.loadConstant(reinterpret_cast<uint32_t>(const_cast<void*>(address)) + 8, scr); + m_assembler.fmovsWriterndec(src, scr); + m_assembler.fmovsWriterndec((FPRegisterID)(src + 1), scr); + releaseScratch(scr); + } + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.daddRegReg(src, dest); @@ -1148,6 +1213,18 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.dsubRegReg(src, dest); } + void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + if (op2 == dest) { + moveDouble(op1, fscratch); + subDouble(op2, fscratch); + moveDouble(fscratch, dest); + } else { + moveDouble(op1, dest); + subDouble(op2, dest); + } + } + void subDouble(Address address, FPRegisterID dest) { loadDouble(address, fscratch); @@ -1159,6 +1236,16 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.dmulRegReg(src, dest); } + void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + if (op1 == dest) + mulDouble(op2, dest); + else { + moveDouble(op2, dest); + mulDouble(op1, dest); + } + } + void mulDouble(Address address, FPRegisterID dest) { loadDouble(address, fscratch); @@ -1170,6 +1257,24 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.ddivRegReg(src, dest); } + void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + if (op2 == dest) { + moveDouble(op1, fscratch); + divDouble(op2, fscratch); + moveDouble(fscratch, dest); + } else { + moveDouble(op1, dest); + divDouble(op2, dest); + } + } + + void negateDouble(FPRegisterID src, FPRegisterID dest) + { + moveDouble(src, dest); + m_assembler.dneg(dest); + } + void convertFloatToDouble(FPRegisterID src, FPRegisterID dst) { m_assembler.fldsfpul(src); @@ -1191,7 +1296,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void convertInt32ToDouble(AbsoluteAddress src, FPRegisterID dest) { RegisterID scr = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(src.m_ptr), scr); + load32(src.m_ptr, scr); convertInt32ToDouble(scr, dest); releaseScratch(scr); } @@ -1214,18 +1319,13 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) if (dest != SH4Registers::r0) move(SH4Registers::r0, scr1); - move(address.index, scr); - lshift32(TrustedImm32(address.scale), scr); - add32(address.base, scr); - - if (address.offset) - add32(TrustedImm32(address.offset), scr); + loadEffectiveAddress(address, scr); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 68, sizeof(uint32_t)); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 58, sizeof(uint32_t)); move(scr, SH4Registers::r0); - m_assembler.andlImm8r(0x3, SH4Registers::r0); - m_assembler.cmpEqImmR0(0x0, SH4Registers::r0); + m_assembler.testlImm8r(0x3, SH4Registers::r0); m_jump = Jump(m_assembler.jne(), SH4Assembler::JumpNear); + if (dest != SH4Registers::r0) move(scr1, SH4Registers::r0); @@ -1233,27 +1333,23 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID 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); + m_assembler.testlImm8r(0x1, 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); + load16PostInc(scr, scr1); load16(scr, dest); 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); + load8PostInc(scr, scr1); + load16PostInc(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); @@ -1300,20 +1396,13 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) } 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.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(right, left); - releaseScratch(scr); Jump m_jump = branchFalse(); end.link(this); return m_jump; @@ -1325,8 +1414,16 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) } if (cond == DoubleGreaterThanOrEqual) { + JumpList end; + m_assembler.dcmppeq(left, left); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } if (cond == DoubleLessThan) { @@ -1335,134 +1432,73 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) } if (cond == DoubleLessThanOrEqual) { + JumpList end; + m_assembler.dcmppeq(left, left); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + end.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); - return branchFalse(); + Jump m_jump = branchFalse(); + end.link(this); + return m_jump; } 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)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppeq(left, right); Jump m_jump = Jump(m_assembler.je()); - end.link(this); - m_assembler.extraInstrForBranch(scr); - releaseScratch(scr); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); 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)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(right, left); Jump m_jump = Jump(m_assembler.je()); - end.link(this); - m_assembler.extraInstrForBranch(scr); - releaseScratch(scr); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); 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)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - 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 m_jump; + return branchFalse(); } 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)); + JumpList takeBranch; + m_assembler.dcmppeq(left, left); m_assembler.ensureSpace(m_assembler.maxInstructionSize + 22, sizeof(uint32_t)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); + m_assembler.dcmppeq(right, right); + takeBranch.append(Jump(m_assembler.jne(), SH4Assembler::JumpNear)); m_assembler.dcmppgt(left, right); Jump m_jump = Jump(m_assembler.je()); - end.link(this); - m_assembler.extraInstrForBranch(scr); - releaseScratch(scr); + takeBranch.link(this); + m_assembler.extraInstrForBranch(scratchReg3); 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)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - 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 m_jump; + return branchFalse(); } 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)); - end.append(Jump(m_assembler.je(), SH4Assembler::JumpNear)); - m_assembler.dcnvds(left); - m_assembler.stsfpulReg(scr); - m_assembler.cmplRegReg(scratchReg3, scr, SH4Condition(Equal)); - 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 m_jump; + return branchFalse(); } Jump branchTrue() @@ -1498,14 +1534,14 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void sqrtDouble(FPRegisterID src, FPRegisterID dest) { - if (dest != src) - m_assembler.dmovRegReg(src, dest); + moveDouble(src, dest); m_assembler.dsqrt(dest); } - void absDouble(FPRegisterID, FPRegisterID) + void absDouble(FPRegisterID src, FPRegisterID dest) { - ASSERT_NOT_REACHED(); + moveDouble(src, dest); + m_assembler.dabs(dest); } Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) @@ -1529,8 +1565,12 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void signExtend32ToPtr(RegisterID src, RegisterID dest) { - if (src != dest) - move(src, dest); + move(src, dest); + } + + void zeroExtend32ToPtr(RegisterID src, RegisterID dest) + { + move(src, dest); } Jump branch8(RelationalCondition cond, Address left, TrustedImm32 right) @@ -1550,17 +1590,77 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) releaseScratch(addressTempRegister); } - Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) + { + Jump result; + truncateDoubleToInt32(src, dest); + RegisterID intscr = claimScratch(); + m_assembler.loadConstant(0x7fffffff, intscr); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 12, sizeof(uint32_t)); + if (branchType == BranchIfTruncateFailed) { + m_assembler.branch(BT_OPCODE, 2); + m_assembler.addlImm8r(1, intscr); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + result = branchTrue(); + } else { + Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear); + m_assembler.addlImm8r(1, intscr); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + result = branchFalse(); + out.link(this); + } + releaseScratch(intscr); + return result; + } + + Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) + { + Jump result; + RegisterID intscr = claimScratch(); + m_assembler.loadConstant(0x80000000, intscr); + convertInt32ToDouble(intscr, fscratch); + addDouble(src, fscratch); + truncateDoubleToInt32(fscratch, dest); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 16, sizeof(uint32_t)); + if (branchType == BranchIfTruncateFailed) { + m_assembler.branch(BT_OPCODE, 4); + m_assembler.addlImm8r(-1, intscr); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + m_assembler.addlImm8r(1, intscr); + m_assembler.sublRegReg(intscr, dest); + result = branchTrue(); + } else { + Jump out = Jump(m_assembler.je(), SH4Assembler::JumpNear); + m_assembler.addlImm8r(-1, intscr); + m_assembler.cmplRegReg(dest, intscr, SH4Condition(Equal)); + m_assembler.addlImm8r(1, intscr); + m_assembler.sublRegReg(intscr, dest); + result = branchFalse(); + out.link(this); + } + releaseScratch(intscr); + return result; + } + + void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) { m_assembler.ftrcdrmfpul(src); m_assembler.stsfpulReg(dest); - m_assembler.loadConstant(0x7fffffff, scratchReg3); - m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal)); - m_assembler.ensureSpace(m_assembler.maxInstructionSize + 14, sizeof(uint32_t)); - m_assembler.branch(BT_OPCODE, 2); - m_assembler.addlImm8r(1, scratchReg3); - m_assembler.cmplRegReg(dest, scratchReg3, SH4Condition(Equal)); - return branchTrue(); + } + + void truncateDoubleToUint32(FPRegisterID src, RegisterID dest) + { + RegisterID intscr = claimScratch(); + m_assembler.loadConstant(0x80000000, intscr); + convertInt32ToDouble(intscr, fscratch); + addDouble(src, fscratch); + m_assembler.ftrcdrmfpul(fscratch); + m_assembler.stsfpulReg(dest); + m_assembler.sublRegReg(intscr, dest); + releaseScratch(intscr); } // Stack manipulation operations @@ -1575,27 +1675,6 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.pushReg(src); } - void push(Address address) - { - if (!address.offset) { - push(address.base); - return; - } - - if ((address.offset < 0) || (address.offset >= 64)) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(address.offset, scr); - m_assembler.addlRegReg(address.base, scr); - m_assembler.movlMemReg(scr, SH4Registers::sp); - m_assembler.addlImm8r(-4, SH4Registers::sp); - releaseScratch(scr); - return; - } - - m_assembler.movlMemReg(address.offset >> 2, address.base, SH4Registers::sp); - m_assembler.addlImm8r(-4, SH4Registers::sp); - } - void push(TrustedImm32 imm) { RegisterID scr = claimScratch(); @@ -1630,9 +1709,13 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.loadConstant(imm.asIntptr(), dest); } - void extuw(RegisterID src, RegisterID dst) + void swap(RegisterID reg1, RegisterID reg2) { - m_assembler.extuw(src, dst); + if (reg1 != reg2) { + xor32(reg1, reg2); + xor32(reg2, reg1); + xor32(reg1, reg2); + } } void compare32(RelationalCondition cond, RegisterID left, RegisterID right, RegisterID dest) @@ -1744,7 +1827,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID scr = claimScratch(); - move(TrustedImm32(reinterpret_cast<uint32_t>(left.m_ptr)), scr); + load32(left.m_ptr, scr); m_assembler.cmplRegReg(right, scr, SH4Condition(cond)); releaseScratch(scr); @@ -1757,7 +1840,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID addressTempRegister = claimScratch(); - m_assembler.loadConstant(reinterpret_cast<uint32_t>(left.m_ptr), addressTempRegister); + move(TrustedImmPtr(left.m_ptr), addressTempRegister); m_assembler.movlMemReg(addressTempRegister, addressTempRegister); compare32(right.m_value, addressTempRegister, cond); releaseScratch(addressTempRegister); @@ -1770,21 +1853,18 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) Jump branch8(RelationalCondition cond, BaseIndex left, TrustedImm32 right) { ASSERT(!(right.m_value & 0xFFFFFF00)); - RegisterID scr = claimScratch(); + RegisterID lefttmp = claimScratch(); - move(left.index, scr); - lshift32(TrustedImm32(left.scale), scr); + loadEffectiveAddress(left, lefttmp); - if (left.offset) - add32(TrustedImm32(left.offset), scr); - add32(left.base, scr); - load8(scr, scr); - RegisterID scr1 = claimScratch(); - m_assembler.loadConstant(right.m_value, scr1); - releaseScratch(scr); - releaseScratch(scr1); + load8(lefttmp, lefttmp); + RegisterID righttmp = claimScratch(); + m_assembler.loadConstant(right.m_value, righttmp); - return branch32(cond, scr, scr1); + Jump result = branch32(cond, lefttmp, righttmp); + releaseScratch(lefttmp); + releaseScratch(righttmp); + return result; } Jump branchTest32(ResultCondition cond, RegisterID reg, RegisterID mask) @@ -1828,6 +1908,8 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) Jump branchTest32(ResultCondition cond, BaseIndex address, TrustedImm32 mask = TrustedImm32(-1)) { + ASSERT((cond == Zero) || (cond == NonZero)); + RegisterID scr = claimScratch(); move(address.index, scr); @@ -1860,60 +1942,102 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void jump(Address address) { RegisterID scr = claimScratch(); - - if ((address.offset < 0) || (address.offset >= 64)) { - m_assembler.loadConstant(address.offset, scr); - m_assembler.addlRegReg(address.base, scr); - m_assembler.movlMemReg(scr, scr); - } else if (address.offset) - m_assembler.movlMemReg(address.offset >> 2, address.base, scr); - else - m_assembler.movlMemReg(address.base, scr); + load32(address, scr); m_assembler.jmpReg(scr); + releaseScratch(scr); + } + void jump(AbsoluteAddress address) + { + RegisterID scr = claimScratch(); + + move(TrustedImmPtr(address.m_ptr), scr); + m_assembler.movlMemReg(scr, scr); + m_assembler.jmpReg(scr); releaseScratch(scr); } // Arithmetic control flow operations - Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) + return branchMul32(cond, TrustedImm32(-1), srcDest, srcDest); + + neg32(srcDest); + + if (cond == Signed) { + m_assembler.cmppz(srcDest); + return branchFalse(); + } + + compare32(0, srcDest, Equal); + return (cond == NonZero) ? branchFalse() : branchTrue(); + } + + Jump branchAdd32(ResultCondition cond, RegisterID src, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { m_assembler.addvlRegReg(src, dest); return branchTrue(); } - if (cond == Signed) { - m_assembler.addlRegReg(src, dest); - // Check if dest is negative + m_assembler.addlRegReg(src, dest); + + if ((cond == Signed) || (cond == PositiveOrZero)) { m_assembler.cmppz(dest); - return branchFalse(); + return (cond == Signed) ? branchFalse() : branchTrue(); } - m_assembler.addlRegReg(src, dest); compare32(0, dest, Equal); + return (cond == NonZero) ? branchFalse() : branchTrue(); + } - if (cond == NonZero) // NotEqual - return branchFalse(); - return branchTrue(); + Jump branchAdd32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + + if (cond == Overflow) { + if (src1 == dest) + m_assembler.addvlRegReg(src2, dest); + else { + move(src2, dest); + m_assembler.addvlRegReg(src1, dest); + } + return branchTrue(); + } + + add32(src1, src2, dest); + + if ((cond == Signed) || (cond == PositiveOrZero)) { + m_assembler.cmppz(dest); + return (cond == Signed) ? branchFalse() : branchTrue(); + } + + compare32(0, dest, Equal); + return (cond == NonZero) ? branchFalse() : branchTrue(); } Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); - move(imm, scratchReg3); - return branchAdd32(cond, scratchReg3, dest); + RegisterID immval = claimScratch(); + move(imm, immval); + Jump result = branchAdd32(cond, immval, dest); + releaseScratch(immval); + return result; } Jump branchAdd32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) { - ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); - if (src != dest) - move(src, dest); + move(src, dest); if (cond == Overflow) { move(imm, scratchReg3); @@ -1923,16 +2047,42 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) add32(imm, dest); - if (cond == Signed) { + if ((cond == Signed) || (cond == PositiveOrZero)) { m_assembler.cmppz(dest); - return branchFalse(); + return (cond == Signed) ? branchFalse() : branchTrue(); } compare32(0, dest, Equal); + return (cond == NonZero) ? branchFalse() : branchTrue(); + } - if (cond == NonZero) // NotEqual - return branchFalse(); - return branchTrue(); + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == PositiveOrZero) || (cond == Zero) || (cond == NonZero)); + bool result; + + move(imm, scratchReg3); + RegisterID destptr = claimScratch(); + RegisterID destval = claimScratch(); + move(TrustedImmPtr(dest.m_ptr), destptr); + m_assembler.movlMemReg(destptr, destval); + if (cond == Overflow) { + m_assembler.addvlRegReg(scratchReg3, destval); + result = true; + } else { + m_assembler.addlRegReg(scratchReg3, destval); + if ((cond == Signed) || (cond == PositiveOrZero)) { + m_assembler.cmppz(destval); + result = (cond == PositiveOrZero); + } else { + m_assembler.testlRegReg(destval, destval); + result = (cond != NonZero); + } + } + m_assembler.movlRegMem(destval, destptr); + releaseScratch(destval); + releaseScratch(destptr); + return result ? branchTrue() : branchFalse(); } Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1940,44 +2090,72 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); if (cond == Overflow) { - RegisterID scr1 = claimScratch(); - RegisterID scr = claimScratch(); - m_assembler.dmullRegReg(src, dest); + RegisterID scrsign = claimScratch(); + RegisterID msbres = claimScratch(); + m_assembler.dmulslRegReg(src, dest); m_assembler.stsmacl(dest); - m_assembler.movImm8(-31, scr); - m_assembler.movlRegReg(dest, scr1); - m_assembler.shaRegReg(scr1, scr); - m_assembler.stsmach(scr); - m_assembler.cmplRegReg(scr, scr1, SH4Condition(Equal)); - releaseScratch(scr1); - releaseScratch(scr); + m_assembler.cmppz(dest); + m_assembler.movt(scrsign); + m_assembler.addlImm8r(-1, scrsign); + m_assembler.stsmach(msbres); + m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal)); + releaseScratch(msbres); + releaseScratch(scrsign); return branchFalse(); } - m_assembler.imullRegReg(src, dest); - m_assembler.stsmacl(dest); + mul32(src, dest); + if (cond == Signed) { - // Check if dest is negative m_assembler.cmppz(dest); return branchFalse(); } compare32(0, dest, static_cast<RelationalCondition>(cond)); + return (cond == NonZero) ? branchFalse() : branchTrue(); + } - if (cond == NonZero) // NotEqual + Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + + if (cond == Overflow) { + RegisterID scrsign = claimScratch(); + RegisterID msbres = claimScratch(); + m_assembler.dmulslRegReg(src1, src2); + m_assembler.stsmacl(dest); + m_assembler.cmppz(dest); + m_assembler.movt(scrsign); + m_assembler.addlImm8r(-1, scrsign); + m_assembler.stsmach(msbres); + m_assembler.cmplRegReg(msbres, scrsign, SH4Condition(Equal)); + releaseScratch(msbres); + releaseScratch(scrsign); return branchFalse(); - return branchTrue(); + } + + mul32(src1, src2, dest); + + if (cond == Signed) { + m_assembler.cmppz(dest); + return branchFalse(); + } + + compare32(0, dest, Equal); + return (cond == NonZero) ? branchFalse() : branchTrue(); } Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); - move(imm, scratchReg3); - if (src != dest) - move(src, dest); + if (src == dest) { + move(imm, scratchReg3); + return branchMul32(cond, scratchReg3, dest); + } - return branchMul32(cond, scratchReg3, dest); + move(imm, dest); + return branchMul32(cond, src, dest); } Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1989,76 +2167,92 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) return branchTrue(); } + sub32(src, dest); + if (cond == Signed) { - // Check if dest is negative - m_assembler.sublRegReg(src, dest); - compare32(0, dest, LessThan); - return branchTrue(); + m_assembler.cmppz(dest); + return branchFalse(); } - sub32(src, dest); compare32(0, dest, static_cast<RelationalCondition>(cond)); - - if (cond == NonZero) // NotEqual - return branchFalse(); - return branchTrue(); + return (cond == NonZero) ? branchFalse() : branchTrue(); } Jump branchSub32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); - move(imm, scratchReg3); - return branchSub32(cond, scratchReg3, dest); + RegisterID immval = claimScratch(); + move(imm, immval); + Jump result = branchSub32(cond, immval, dest); + releaseScratch(immval); + return result; } Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) { - move(imm, scratchReg3); - if (src != dest) - move(src, dest); - return branchSub32(cond, scratchReg3, dest); + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + + move(src, dest); + return branchSub32(cond, imm, dest); } Jump branchSub32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) { - if (src1 != dest) + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + + if (src2 != dest) { move(src1, dest); - return branchSub32(cond, src2, dest); + return branchSub32(cond, src2, dest); + } + + if (cond == Overflow) { + RegisterID tmpval = claimScratch(); + move(src1, tmpval); + m_assembler.subvlRegReg(src2, tmpval); + move(tmpval, dest); + releaseScratch(tmpval); + return branchTrue(); + } + + RegisterID tmpval = claimScratch(); + move(src1, tmpval); + sub32(src2, tmpval); + move(tmpval, dest); + releaseScratch(tmpval); + + if (cond == Signed) { + m_assembler.cmppz(dest); + return branchFalse(); + } + + compare32(0, dest, static_cast<RelationalCondition>(cond)); + return (cond == NonZero) ? branchFalse() : branchTrue(); } Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Signed) || (cond == Zero) || (cond == NonZero)); + or32(src, dest); + if (cond == Signed) { - or32(src, dest); - compare32(0, dest, static_cast<RelationalCondition>(LessThan)); - return branchTrue(); + m_assembler.cmppz(dest); + return branchFalse(); } - or32(src, dest); compare32(0, dest, static_cast<RelationalCondition>(cond)); - - if (cond == NonZero) // NotEqual - return branchFalse(); - return branchTrue(); + return (cond == NonZero) ? branchFalse() : branchTrue(); } - void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp) + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID, bool negZeroCheck = true) { - m_assembler.ftrcdrmfpul(src); - m_assembler.stsfpulReg(dest); + truncateDoubleToInt32(src, dest); convertInt32ToDouble(dest, fscratch); failureCases.append(branchDouble(DoubleNotEqualOrUnordered, fscratch, src)); - if (dest == SH4Registers::r0) - m_assembler.cmpEqImmR0(0, dest); - else { - m_assembler.movImm8(0, scratchReg3); - m_assembler.cmplRegReg(scratchReg3, dest, SH4Condition(Equal)); - } - failureCases.append(branchTrue()); + if (negZeroCheck) + failureCases.append(branch32(Equal, dest, TrustedImm32(0))); } void neg32(RegisterID dst) @@ -2068,31 +2262,40 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void urshift32(RegisterID shiftamount, RegisterID dest) { - if (shiftamount == SH4Registers::r0) - m_assembler.andlImm8r(0x1f, shiftamount); - else { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(0x1f, scr); - m_assembler.andlRegReg(scr, shiftamount); - releaseScratch(scr); - } - m_assembler.neg(shiftamount, shiftamount); - m_assembler.shllRegReg(dest, shiftamount); + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(0x1f, shiftTmp); + m_assembler.andlRegReg(shiftamount, shiftTmp); + m_assembler.neg(shiftTmp, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); + } + + void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + move(src, dest); + urshift32(shiftAmount, dest); } void urshift32(TrustedImm32 imm, RegisterID dest) { - RegisterID scr = claimScratch(); - m_assembler.loadConstant(-(imm.m_value & 0x1f), scr); - m_assembler.shaRegReg(dest, scr); - releaseScratch(scr); + int immMasked = imm.m_value & 0x1f; + if (!immMasked) + return; + + if ((immMasked == 1) || (immMasked == 2) || (immMasked == 8) || (immMasked == 16)) { + m_assembler.shlrImm8r(immMasked, dest); + return; + } + + RegisterID shiftTmp = claimScratch(); + m_assembler.loadConstant(-immMasked, shiftTmp); + m_assembler.shldRegReg(dest, shiftTmp); + releaseScratch(shiftTmp); } void urshift32(RegisterID src, TrustedImm32 shiftamount, RegisterID dest) { - if (src != dest) - move(src, dest); - + move(src, dest); urshift32(shiftamount, dest); } @@ -2121,6 +2324,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void breakpoint() { + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 2); m_assembler.bkpt(); m_assembler.nop(); } @@ -2129,6 +2333,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) { RegisterID dataTempRegister = claimScratch(); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t)); dataLabel = moveWithPatch(initialRightValue, dataTempRegister); m_assembler.cmplRegReg(dataTempRegister, left, SH4Condition(cond)); releaseScratch(dataTempRegister); @@ -2146,6 +2351,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) m_assembler.addlRegReg(left.base, scr); m_assembler.movlMemReg(scr, scr); RegisterID scr1 = claimScratch(); + m_assembler.ensureSpace(m_assembler.maxInstructionSize + 10, 2 * sizeof(uint32_t)); dataLabel = moveWithPatch(initialRightValue, scr1); m_assembler.cmplRegReg(scr1, scr, SH4Condition(cond)); releaseScratch(scr); @@ -2207,13 +2413,12 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) { - ASSERT_NOT_REACHED(); + SH4Assembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); } static ptrdiff_t maxJumpReplacementSize() { - ASSERT_NOT_REACHED(); - return 0; + return SH4Assembler::maxJumpReplacementSize(); } static bool canJumpReplacePatchableBranchPtrWithPatch() { return false; } @@ -2223,9 +2428,9 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) return label.labelAtOffset(0); } - static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue) { - SH4Assembler::revertJump(instructionStart.dataLocation(), reinterpret_cast<uintptr_t>(initialValue) & 0xffff); + SH4Assembler::revertJumpToMove(instructionStart.dataLocation(), rd, reinterpret_cast<int>(initialValue)); } static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) @@ -2253,9 +2458,20 @@ private: friend class LinkBuffer; friend class RepatchBuffer; - static void linkCall(void*, Call, FunctionPtr); - static void repatchCall(CodeLocationCall, CodeLocationLabel); - static void repatchCall(CodeLocationCall, FunctionPtr); + static void linkCall(void* code, Call call, FunctionPtr function) + { + SH4Assembler::linkCall(code, call.m_label, function.value()); + } + + static void repatchCall(CodeLocationCall call, CodeLocationLabel destination) + { + SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } + + static void repatchCall(CodeLocationCall call, FunctionPtr destination) + { + SH4Assembler::relinkCall(call.dataLocation(), destination.executableAddress()); + } }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h index 53cb80c21..f171dc408 100644 --- a/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h +++ b/Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h @@ -68,6 +68,7 @@ public: enum ResultCondition { Overflow = X86Assembler::ConditionO, Signed = X86Assembler::ConditionS, + PositiveOrZero = X86Assembler::ConditionNS, Zero = X86Assembler::ConditionE, NonZero = X86Assembler::ConditionNE }; @@ -884,13 +885,14 @@ 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 fpTemp) + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID fpTemp, bool negZeroCheck = true) { ASSERT(isSSE2Present()); m_assembler.cvttsd2si_rr(src, dest); // 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)); // Convert the integer result back to float & compare to the original value - if not equal or unordered (NaN) then jump. convertInt32ToDouble(dest, fpTemp); diff --git a/Source/JavaScriptCore/assembler/SH4Assembler.h b/Source/JavaScriptCore/assembler/SH4Assembler.h index 39f5585be..fded7df89 100644 --- a/Source/JavaScriptCore/assembler/SH4Assembler.h +++ b/Source/JavaScriptCore/assembler/SH4Assembler.h @@ -1,4 +1,5 @@ /* + * Copyright (C) 2013 Cisco Systems, Inc. All rights reserved. * Copyright (C) 2009-2011 STMicroelectronics. All rights reserved. * Copyright (C) 2008 Apple Inc. All rights reserved. * @@ -114,7 +115,9 @@ enum { MOVL_READ_OFFPC_OPCODE = 0xd000, MOVL_READ_OFFRM_OPCODE = 0x5000, MOVW_WRITE_RN_OPCODE = 0x2001, + MOVW_WRITE_R0RN_OPCODE = 0x0005, MOVW_READ_RM_OPCODE = 0x6001, + MOVW_READ_RMINC_OPCODE = 0x6005, MOVW_READ_R0RM_OPCODE = 0x000d, MOVW_READ_OFFRM_OPCODE = 0x8500, MOVW_READ_OFFPC_OPCODE = 0x9000, @@ -175,6 +178,7 @@ enum { STSFPSCR_OPCODE = 0x006a, LDSRMFPUL_OPCODE = 0x405a, FSTSFPULFRN_OPCODE = 0xf00d, + FABS_OPCODE = 0xf05d, FSQRT_OPCODE = 0xf06d, FSCHG_OPCODE = 0xf3fd, CLRT_OPCODE = 8, @@ -333,30 +337,33 @@ public: }; SH4Assembler() + : m_claimscratchReg(0x0) + , m_indexOfLastWatchpoint(INT_MIN) + , m_indexOfTailOfLastWatchpoint(INT_MIN) { - m_claimscratchReg = 0x0; } // SH4 condition codes typedef enum { EQ = 0x0, // Equal NE = 0x1, // Not Equal - HS = 0x2, // Unsigend Greater Than equal - HI = 0x3, // Unsigend Greater Than - LS = 0x4, // Unsigend Lower or Same - LI = 0x5, // Unsigend Lower + HS = 0x2, // Unsigned Greater Than equal + HI = 0x3, // Unsigned Greater Than + LS = 0x4, // Unsigned Lower or Same + LI = 0x5, // Unsigned Lower GE = 0x6, // Greater or Equal LT = 0x7, // Less Than GT = 0x8, // Greater Than LE = 0x9, // Less or Equal OF = 0xa, // OverFlow SI = 0xb, // Signed - EQU= 0xc, // Equal or unordered(NaN) - NEU= 0xd, - GTU= 0xe, - GEU= 0xf, - LTU= 0x10, - LEU= 0x11, + NS = 0xc, // Not Signed + EQU= 0xd, // Equal or unordered(NaN) + NEU= 0xe, + GTU= 0xf, + GEU= 0x10, + LTU= 0x11, + LEU= 0x12, } Condition; // Opaque label types @@ -534,7 +541,7 @@ public: oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -544,28 +551,14 @@ public: oneShortOp(opc); } - void shllRegReg(RegisterID dst, RegisterID rShift) + void shldRegReg(RegisterID dst, RegisterID rShift) { - uint16_t opc = getOpcodeGroup1(SHLD_OPCODE, dst, rShift); - oneShortOp(opc); - } - - void shlrRegReg(RegisterID dst, RegisterID rShift) - { - neg(rShift, rShift); - shllRegReg(dst, rShift); + oneShortOp(getOpcodeGroup1(SHLD_OPCODE, dst, rShift)); } - void sharRegReg(RegisterID dst, RegisterID rShift) + void shadRegReg(RegisterID dst, RegisterID rShift) { - neg(rShift, rShift); - shaRegReg(dst, rShift); - } - - void shaRegReg(RegisterID dst, RegisterID rShift) - { - uint16_t opc = getOpcodeGroup1(SHAD_OPCODE, dst, rShift); - oneShortOp(opc); + oneShortOp(getOpcodeGroup1(SHAD_OPCODE, dst, rShift)); } void shlrImm8r(int imm, RegisterID dst) @@ -584,7 +577,29 @@ public: oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); + } + } + + void shalImm8r(int imm, RegisterID dst) + { + switch (imm) { + case 1: + oneShortOp(getOpcodeGroup2(SHAL_OPCODE, dst)); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); + } + } + + void sharImm8r(int imm, RegisterID dst) + { + switch (imm) { + case 1: + oneShortOp(getOpcodeGroup2(SHAR_OPCODE, dst)); + break; + default: + RELEASE_ASSERT_NOT_REACHED(); } } @@ -654,7 +669,7 @@ public: oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -731,7 +746,7 @@ public: oneShortOp(getOpcodeGroup5(BF_OPCODE, label)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -751,7 +766,7 @@ public: oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -817,6 +832,12 @@ public: oneShortOp(opc, true, false); } + void fmovsRegReg(FPRegisterID src, FPRegisterID dst) + { + uint16_t opc = getOpcodeGroup1(FMOV_OPCODE, dst, src); + oneShortOp(opc, true, false); + } + void fmovsReadrm(RegisterID src, FPRegisterID dst) { uint16_t opc = getOpcodeGroup1(FMOVS_READ_RM_OPCODE, dst, src); @@ -939,6 +960,12 @@ public: oneShortOp(opc); } + void dabs(FPRegisterID dst) + { + uint16_t opc = getOpcodeGroup7(FABS_OPCODE, dst >> 1); + oneShortOp(opc); + } + void dsqrt(FPRegisterID dst) { uint16_t opc = getOpcodeGroup7(FSQRT_OPCODE, dst >> 1); @@ -1027,6 +1054,12 @@ public: oneShortOp(opc); } + void movwMemRegIn(RegisterID base, RegisterID dst) + { + uint16_t opc = getOpcodeGroup1(MOVW_READ_RMINC_OPCODE, dst, base); + oneShortOp(opc); + } + void movwPCReg(int offset, RegisterID base, RegisterID dst) { ASSERT(base == SH4Registers::pc); @@ -1050,6 +1083,12 @@ public: oneShortOp(opc); } + void movwRegMemr0(RegisterID src, RegisterID dst) + { + uint16_t opc = getOpcodeGroup1(MOVW_WRITE_R0RN_OPCODE, dst, src); + oneShortOp(opc); + } + void movlRegMem(RegisterID src, int offset, RegisterID base) { ASSERT((offset <= 15) && (offset >= 0)); @@ -1116,6 +1155,18 @@ public: oneShortOp(opc); } + void movbMemRegIn(RegisterID base, RegisterID dst) + { + uint16_t opc = getOpcodeGroup1(MOVB_READ_RMINC_OPCODE, dst, base); + oneShortOp(opc); + } + + void movbRegMemr0(RegisterID src, RegisterID dst) + { + uint16_t opc = getOpcodeGroup1(MOVB_WRITE_R0RN_OPCODE, dst, src); + oneShortOp(opc); + } + void movlMemReg(RegisterID base, RegisterID dst) { uint16_t opc = getOpcodeGroup1(MOVL_READ_RM_OPCODE, dst, base); @@ -1140,14 +1191,6 @@ public: oneShortOp(opc); } - void movlImm8r(int imm8, RegisterID dst) - { - ASSERT((imm8 <= 127) && (imm8 >= -128)); - - uint16_t opc = getOpcodeGroup3(MOVIMM_OPCODE, dst, imm8); - oneShortOp(opc); - } - void loadConstant(uint32_t constant, RegisterID dst) { if (((int)constant <= 0x7f) && ((int)constant >= -0x80)) { @@ -1259,10 +1302,25 @@ public: return m_buffer.label(); } - AssemblerLabel label() + AssemblerLabel labelForWatchpoint() { m_buffer.ensureSpaceForAnyInstruction(); - return m_buffer.label(); + AssemblerLabel result = m_buffer.label(); + if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint) + result = label(); + m_indexOfLastWatchpoint = result.m_offset; + m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); + return result; + } + + AssemblerLabel label() + { + AssemblerLabel result = labelIgnoringWatchpoints(); + while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { + nop(); + result = labelIgnoringWatchpoints(); + } + return result; } int sizeOfConstantPool() @@ -1282,12 +1340,14 @@ public: static void changePCrelativeAddress(int offset, uint16_t* instructionPtr, uint32_t newAddress) { + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3)); *reinterpret_cast<uint32_t*>(address) = newAddress; } static uint32_t readPCrelativeAddress(int offset, uint16_t* instructionPtr) { + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); uint32_t address = (offset << 2) + ((reinterpret_cast<uint32_t>(instructionPtr) + 4) &(~0x3)); return *reinterpret_cast<uint32_t*>(address); } @@ -1325,17 +1385,9 @@ public: braf @reg braf @reg nop nop */ - ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); - - offsetBits -= 4; - if (offsetBits >= -4096 && offsetBits <= 4094) { - *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); - *(++instructionPtr) = NOP_OPCODE; - printBlockInstr(instructionPtr - 1, from.m_offset, 2); - return; - } - - changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); + ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE); + changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6); printInstr(*instructionPtr, from.m_offset + 2); } @@ -1343,12 +1395,14 @@ public: { uint16_t* instructionPtr = getInstructionPtr(code, from.m_offset); instructionPtr -= 3; + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to)); } static void linkPointer(void* code, AssemblerLabel where, void* value) { uint16_t* instructionPtr = getInstructionPtr(code, where.m_offset); + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(value)); } @@ -1370,7 +1424,7 @@ public: static SH4Buffer::TwoShorts placeConstantPoolBarrier(int offset) { - ASSERT(((offset >> 1) <=2047) && ((offset >> 1) >= -2048)); + ASSERT(((offset >> 1) <= 2047) && ((offset >> 1) >= -2048)); SH4Buffer::TwoShorts m_barrier; m_barrier.high = (BRA_OPCODE | (offset >> 1)); @@ -1392,7 +1446,7 @@ public: ASSERT((((reinterpret_cast<uint32_t>(constPoolAddr) - reinterpret_cast<uint32_t>(loadAddr)) + index * 4)) < 1024); int offset = reinterpret_cast<uint32_t>(constPoolAddr) + (index * 4) - ((reinterpret_cast<uint32_t>(instructionPtr) & ~0x03) + 4); - instruction &=0xf00; + instruction &= 0x0f00; instruction |= 0xd000; offset &= 0x03ff; instruction |= (offset >> 2); @@ -1413,6 +1467,7 @@ public: static void repatchInt32(void* where, int32_t value) { uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(where); + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, value); } @@ -1428,6 +1483,7 @@ public: { uint16_t* instructionPtr = reinterpret_cast<uint16_t*>(from); instructionPtr -= 3; + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, reinterpret_cast<uint32_t>(to)); } @@ -1440,40 +1496,68 @@ public: if (((*instructionPtr & 0xff00) == BT_OPCODE) || ((*instructionPtr & 0xff00) == BF_OPCODE)) { offsetBits -= 8; instructionPtr++; + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits); instruction = (BRAF_OPCODE | (*instructionPtr++ & 0xf00)); *instructionPtr = instruction; printBlockInstr(instructionPtr, reinterpret_cast<uint32_t>(from) + 1, 3); + cacheFlush(instructionPtr, sizeof(SH4Word)); return; } - ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); - offsetBits -= 4; - if (offsetBits >= -4096 && offsetBits <= 4094) { - *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); - *(++instructionPtr) = NOP_OPCODE; - printBlockInstr(instructionPtr - 2, reinterpret_cast<uint32_t>(from), 2); - return; - } - - changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); + ASSERT((instructionPtr[1] & 0xf0ff) == BRAF_OPCODE); + changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 6); printInstr(*instructionPtr, reinterpret_cast<uint32_t>(from)); } // Linking & patching - static void revertJump(void* instructionStart, SH4Word imm) + static ptrdiff_t maxJumpReplacementSize() { - SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart); - SH4Word disp; + return sizeof(SH4Word) * 6; + } + static void replaceWithJump(void *instructionStart, void *to) + { + SH4Word* instruction = reinterpret_cast<SH4Word*>(instructionStart); + intptr_t difference = reinterpret_cast<intptr_t>(to) - (reinterpret_cast<intptr_t>(instruction) + 2 * sizeof(SH4Word)); + + if ((instruction[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE) { + instruction[1] = (BRAF_OPCODE | (instruction[0] & 0x0f00)); + instruction[2] = NOP_OPCODE; + cacheFlush(&instruction[1], 2 * sizeof(SH4Word)); + } else { + instruction[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, 1); + instruction[1] = getOpcodeGroup2(BRAF_OPCODE, SH4Registers::r13); + instruction[2] = NOP_OPCODE; + cacheFlush(instruction, 3 * sizeof(SH4Word)); + } + + changePCrelativeAddress(instruction[0] & 0x00ff, instruction, difference - 2); + } + + static void revertJumpToMove(void* instructionStart, RegisterID rd, int imm) + { + SH4Word *insn = reinterpret_cast<SH4Word*>(instructionStart); ASSERT((insn[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); - disp = insn[0] & 0x00ff; - insn += 2 + (disp << 1); // PC += 4 + (disp*4) - insn = (SH4Word *) ((unsigned) insn & (~3)); - insn[0] = imm; - cacheFlush(insn, sizeof(SH4Word)); + if ((insn[1] & 0xf000) == CMPEQ_OPCODE) { + insn[0] = getOpcodeGroup3(MOVL_READ_OFFPC_OPCODE, SH4Registers::r13, insn[0] & 0x00ff); + insn[1] = (insn[1] & 0xf00f) | (rd << 8) | (SH4Registers::r13 << 4); + cacheFlush(insn, 2 * sizeof(SH4Word)); + changePCrelativeAddress(insn[0] & 0x00ff, insn, imm); + return; + } + + if ((insn[0] & 0x00ff) == 1) + insn[1] = getOpcodeGroup6(BRA_OPCODE, 3); + else + insn[1] = NOP_OPCODE; + + insn[2] = NOP_OPCODE; + cacheFlush(&insn[1], 2 * sizeof(SH4Word)); + + changePCrelativeAddress(insn[0] & 0x00ff, insn, imm); } void linkJump(AssemblerLabel from, AssemblerLabel to, JumpType type = JumpFar) @@ -1486,8 +1570,9 @@ public: int offsetBits; if (type == JumpNear) { - ASSERT((instruction == BT_OPCODE) || (instruction == BF_OPCODE) || (instruction == BRA_OPCODE)); int offset = (codeSize() - from.m_offset) - 4; + ASSERT((((instruction == BT_OPCODE) || (instruction == BF_OPCODE)) && (offset >= -256) && (offset <= 254)) + || ((instruction == BRA_OPCODE) && (offset >= -4096) && (offset <= 4094))); *instructionPtr++ = instruction | (offset >> 1); printInstr(*instructionPtr, from.m_offset + 2); return; @@ -1502,7 +1587,7 @@ public: offsetBits = (to.m_offset - from.m_offset) - 8; instruction ^= 0x0202; *instructionPtr++ = instruction; - if ((*instructionPtr & 0xf000) == 0xe000) { + if ((*instructionPtr & 0xf000) == MOVIMM_OPCODE) { uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress()); *addr = offsetBits; } else @@ -1518,23 +1603,18 @@ public: nop nop */ ASSERT((*(instructionPtr + 1) & BRAF_OPCODE) == BRAF_OPCODE); - offsetBits = (to.m_offset - from.m_offset) - 4; - if (offsetBits >= -4096 && offsetBits <= 4094) { - *instructionPtr = getOpcodeGroup6(BRA_OPCODE, offsetBits >> 1); - *(++instructionPtr) = NOP_OPCODE; - printBlockInstr(instructionPtr - 1, from.m_offset, 2); - return; - } + offsetBits = (to.m_offset - from.m_offset) - 6; instruction = *instructionPtr; - if ((instruction & 0xf000) == 0xe000) { + if ((instruction & 0xf000) == MOVIMM_OPCODE) { uint32_t* addr = getLdrImmAddressOnPool(instructionPtr, m_buffer.poolAddress()); - *addr = offsetBits - 2; + *addr = offsetBits; printInstr(*instructionPtr, from.m_offset + 2); return; } - changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits - 2); + ASSERT((instructionPtr[0] & 0xf000) == MOVL_READ_OFFPC_OPCODE); + changePCrelativeAddress((*instructionPtr & 0xff), instructionPtr, offsetBits); printInstr(*instructionPtr, from.m_offset + 2); } @@ -1575,19 +1655,27 @@ public: return reinterpret_cast<void*>(readPCrelativeAddress((*instructionPtr & 0xff), instructionPtr)); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { - return m_buffer.executableCopy(globalData, ownerUID, effort); + return m_buffer.executableCopy(vm, ownerUID, effort); } static void cacheFlush(void* code, size_t size) { -#if !OS(LINUX) -#error "The cacheFlush support is missing on this platform." -#elif defined CACHEFLUSH_D_L2 - syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2); +#if OS(LINUX) + // Flush each page separately, otherwise the whole flush will fail if an uncommited page is in the area. + unsigned currentPage = reinterpret_cast<unsigned>(code) & ~(pageSize() - 1); + unsigned lastPage = (reinterpret_cast<unsigned>(code) + size - 1) & ~(pageSize() - 1); + do { +#if defined CACHEFLUSH_D_L2 + syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I | CACHEFLUSH_D_L2); +#else + syscall(__NR_cacheflush, currentPage, pageSize(), CACHEFLUSH_D_WB | CACHEFLUSH_I); +#endif + currentPage += pageSize(); + } while (lastPage >= currentPage); #else - syscall(__NR_cacheflush, reinterpret_cast<unsigned>(code), size, CACHEFLUSH_D_WB | CACHEFLUSH_I); +#error "The cacheFlush support is missing on this platform." #endif } @@ -1619,6 +1707,8 @@ public: void* data() const { return m_buffer.data(); } size_t codeSize() const { return m_buffer.codeSize(); } + unsigned debugOffset() { return m_buffer.debugOffset(); } + #ifdef SH4_ASSEMBLER_TRACING static void printInstr(uint16_t opc, unsigned size, bool isdoubleInst = true) { @@ -1763,6 +1853,9 @@ public: case FTRC_OPCODE: format = " FTRC FR%d, FPUL\n"; break; + case FABS_OPCODE: + format = " FABS FR%d\n"; + break; case FSQRT_OPCODE: format = " FSQRT FR%d\n"; break; @@ -1897,9 +1990,15 @@ public: case MOVW_READ_RM_OPCODE: format = " MOV.W @R%d, R%d\n"; break; + case MOVW_READ_RMINC_OPCODE: + format = " MOV.W @R%d+, R%d\n"; + break; case MOVW_READ_R0RM_OPCODE: format = " MOV.W @(R0, R%d), R%d\n"; break; + case MOVW_WRITE_R0RN_OPCODE: + format = " MOV.W R%d, @(R0, R%d)\n"; + break; case EXTUB_OPCODE: format = " EXTU.B R%d, R%d\n"; break; @@ -2143,6 +2242,8 @@ public: private: SH4Buffer m_buffer; int m_claimscratchReg; + int m_indexOfLastWatchpoint; + int m_indexOfTailOfLastWatchpoint; }; } // namespace JSC diff --git a/Source/JavaScriptCore/assembler/X86Assembler.h b/Source/JavaScriptCore/assembler/X86Assembler.h index 25ff6f0a5..2883e0a4c 100644 --- a/Source/JavaScriptCore/assembler/X86Assembler.h +++ b/Source/JavaScriptCore/assembler/X86Assembler.h @@ -1952,7 +1952,7 @@ public: *ptr = OP_MOV_GvEv; break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -1970,7 +1970,7 @@ public: case OP_LEA: break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -1991,9 +1991,9 @@ public: return b.m_offset - a.m_offset; } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { - return m_formatter.executableCopy(globalData, ownerUID, effort); + return m_formatter.executableCopy(vm, ownerUID, effort); } unsigned debugOffset() { return m_formatter.debugOffset(); } @@ -2349,9 +2349,9 @@ private: bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } void* data() const { return m_buffer.data(); } - PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) + PassRefPtr<ExecutableMemoryHandle> executableCopy(VM& vm, void* ownerUID, JITCompilationEffort effort) { - return m_buffer.executableCopy(globalData, ownerUID, effort); + return m_buffer.executableCopy(vm, ownerUID, effort); } unsigned debugOffset() { return m_buffer.debugOffset(); } |