From fd09b7d9b54ccb4d737747ee7fba26f15f4901cd Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Fri, 12 Apr 2013 12:58:29 +0200 Subject: WTF/JSC update to r148273 This brings in various bug fixes in the ARM and MIPS assemblers as well as a Yarr crash fix and performance fix. This change doesn't compile as-is, but the next change will apply the modifications necessary to compile. That'll make future updates easier as it allows for cherry-picking because the modifications are usually always the same. Change-Id: Iac32f62c71e8ff908deb41f28f12fbc98c0823e1 Reviewed-by: Lars Knoll --- src/3rdparty/masm/assembler/ARMAssembler.cpp | 24 +- src/3rdparty/masm/assembler/ARMAssembler.h | 71 +-- src/3rdparty/masm/assembler/ARMv7Assembler.h | 114 ++++- .../masm/assembler/AbstractMacroAssembler.h | 54 ++- src/3rdparty/masm/assembler/AssemblerBuffer.h | 6 +- src/3rdparty/masm/assembler/LinkBuffer.cpp | 2 +- src/3rdparty/masm/assembler/MIPSAssembler.h | 109 ++++- src/3rdparty/masm/assembler/MacroAssembler.h | 41 +- src/3rdparty/masm/assembler/MacroAssemblerARM.h | 47 +- src/3rdparty/masm/assembler/MacroAssemblerARMv7.h | 15 +- .../masm/assembler/MacroAssemblerCodeRef.h | 7 - src/3rdparty/masm/assembler/MacroAssemblerMIPS.h | 491 +++++++++++++++++++-- src/3rdparty/masm/assembler/MacroAssemblerSH4.h | 6 +- src/3rdparty/masm/assembler/SH4Assembler.h | 10 +- src/3rdparty/masm/assembler/X86Assembler.h | 4 +- 15 files changed, 845 insertions(+), 156 deletions(-) (limited to 'src/3rdparty/masm/assembler') diff --git a/src/3rdparty/masm/assembler/ARMAssembler.cpp b/src/3rdparty/masm/assembler/ARMAssembler.cpp index 9655557a5d..6912d1ea39 100644 --- a/src/3rdparty/masm/assembler/ARMAssembler.cpp +++ b/src/3rdparty/masm/assembler/ARMAssembler.cpp @@ -297,8 +297,15 @@ void ARMAssembler::baseIndexTransfer32(DataTransferTypeA transferType, RegisterI return; } - add(ARMRegisters::S1, base, op2); - dataTransfer32(transferType, srcDst, ARMRegisters::S1, offset); + if (offset <= 0xfffff && offset >= -0xfffff) { + add(ARMRegisters::S0, base, op2); + dataTransfer32(transferType, srcDst, ARMRegisters::S0, offset); + return; + } + + moveImm(offset, ARMRegisters::S0); + add(ARMRegisters::S0, ARMRegisters::S0, op2); + dtrUpRegister(transferType, srcDst, base, ARMRegisters::S0); } void ARMAssembler::dataTransfer16(DataTransferTypeB transferType, RegisterID srcDst, RegisterID base, int32_t offset) @@ -333,8 +340,17 @@ void ARMAssembler::baseIndexTransfer16(DataTransferTypeB transferType, RegisterI return; } - add(ARMRegisters::S1, base, lsl(index, scale)); - dataTransfer16(transferType, srcDst, ARMRegisters::S1, offset); + ARMWord op2 = lsl(index, scale); + + if (offset <= 0xffff && offset >= -0xffff) { + add(ARMRegisters::S0, base, op2); + dataTransfer16(transferType, srcDst, ARMRegisters::S0, offset); + return; + } + + moveImm(offset, ARMRegisters::S0); + add(ARMRegisters::S0, ARMRegisters::S0, op2); + halfDtrUpRegister(transferType, srcDst, base, ARMRegisters::S0); } void ARMAssembler::dataTransferFloat(DataTransferTypeFloat transferType, FPRegisterID srcDst, RegisterID base, int32_t offset) diff --git a/src/3rdparty/masm/assembler/ARMAssembler.h b/src/3rdparty/masm/assembler/ARMAssembler.h index ebab46d98a..3888226b21 100644 --- a/src/3rdparty/masm/assembler/ARMAssembler.h +++ b/src/3rdparty/masm/assembler/ARMAssembler.h @@ -402,13 +402,6 @@ namespace JSC { emitInstruction(toARMWord(cc) | MOV | SetConditionalCodes, rd, ARMRegisters::r0, op2); } - static void revertJump(void* instructionStart, RegisterID rd, ARMWord imm) - { - ARMWord* insn = reinterpret_cast(instructionStart); - ARMWord* address = getLdrImmAddress(insn); - *address = imm; - } - void bic(int rd, int rn, ARMWord op2, Condition cc = AL) { emitInstruction(toARMWord(cc) | BIC, rd, rn, op2); @@ -904,7 +897,7 @@ namespace JSC { static void replaceWithJump(void* instructionStart, void* to) { - ARMWord* instruction = reinterpret_cast(instructionStart) - 1; + ARMWord* instruction = reinterpret_cast(instructionStart); intptr_t difference = reinterpret_cast(to) - (reinterpret_cast(instruction) + DefaultPrefetchOffset * sizeof(ARMWord)); if (!(difference & 1)) { @@ -952,6 +945,17 @@ namespace JSC { } } + static void revertBranchPtrWithPatch(void* instructionStart, RegisterID rn, ARMWord imm) + { + ARMWord* instruction = reinterpret_cast(instructionStart); + + ASSERT((instruction[2] & LdrPcImmediateInstructionMask) == LdrPcImmediateInstruction); + instruction[0] = toARMWord(AL) | ((instruction[2] & 0x0fff0fff) + sizeof(ARMWord)) | RD(ARMRegisters::S1); + *getLdrImmAddress(instruction) = imm; + instruction[1] = toARMWord(AL) | CMP | SetConditionalCodes | RN(rn) | RM(ARMRegisters::S1); + cacheFlush(instruction, 2 * sizeof(ARMWord)); + } + // Address operations static void* getRelocatedAddress(void* code, AssemblerLabel label) @@ -1018,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(code) & ~(pageSize() - 1); - uintptr_t lastPage = (reinterpret_cast(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(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/src/3rdparty/masm/assembler/ARMv7Assembler.h b/src/3rdparty/masm/assembler/ARMv7Assembler.h index b93ec6e63f..7dcf656921 100644 --- a/src/3rdparty/masm/assembler/ARMv7Assembler.h +++ b/src/3rdparty/masm/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 @@ -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 { @@ -1262,6 +1266,20 @@ public: m_formatter.twoWordOp5i6Imm4Reg4EncodedImm(OP_MOV_imm_T3, imm.m_value.imm4, rd, imm); } +#if OS(LINUX) || OS(QNX) + static void revertJumpTo_movT3movtcmpT2(void* instructionStart, RegisterID left, RegisterID right, uintptr_t imm) + { + uint16_t* address = static_cast(instructionStart); + ARMThumbImmediate lo16 = ARMThumbImmediate::makeUInt16(static_cast(imm)); + ARMThumbImmediate hi16 = ARMThumbImmediate::makeUInt16(static_cast(imm >> 16)); + address[0] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOV_imm_T3, lo16); + address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, lo16); + address[2] = twoWordOp5i6Imm4Reg4EncodedImmFirst(OP_MOVT, hi16); + address[3] = twoWordOp5i6Imm4Reg4EncodedImmSecond(right, hi16); + address[4] = OP_CMP_reg_T2 | left; + cacheFlush(address, sizeof(uint16_t) * 5); + } +#else static void revertJumpTo_movT3(void* instructionStart, RegisterID rd, ARMThumbImmediate imm) { ASSERT(imm.isValid()); @@ -1273,6 +1291,7 @@ public: address[1] = twoWordOp5i6Imm4Reg4EncodedImmSecond(rd, imm); cacheFlush(address, sizeof(uint16_t) * 2); } +#endif ALWAYS_INLINE void mov(RegisterID rd, ARMThumbImmediate imm) { @@ -1388,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)); @@ -1724,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); @@ -1858,7 +1897,12 @@ public: { m_formatter.oneWordOp8Imm8(OP_NOP_T1, 0); } - + + void nopw() + { + m_formatter.twoWordOp16Op16(OP_NOP_T2a, OP_NOP_T2b); + } + AssemblerLabel labelIgnoringWatchpoints() { return m_formatter.label(); @@ -1878,7 +1922,10 @@ public: { AssemblerLabel result = m_formatter.label(); while (UNLIKELY(static_cast(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { - nop(); + if (UNLIKELY(static_cast(result.m_offset) + 4 <= m_indexOfTailOfLastWatchpoint)) + nopw(); + else + nop(); result = m_formatter.label(); } return result; @@ -1988,7 +2035,7 @@ public: offsets[ptr++] = offset; } - Vector& jumpsToLink() + Vector& jumpsToLink() { std::sort(m_jumpsToLink.begin(), m_jumpsToLink.end(), linkRecordSourceComparator); return m_jumpsToLink; @@ -2019,7 +2066,7 @@ public: linkBX(reinterpret_cast_ptr(from), to); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); break; } } @@ -2136,15 +2183,31 @@ public: { ASSERT(!(bitwise_cast(instructionStart) & 1)); ASSERT(!(bitwise_cast(to) & 1)); + +#if OS(LINUX) || OS(QNX) + if (canBeJumpT4(reinterpret_cast(instructionStart), to)) { + uint16_t* ptr = reinterpret_cast(instructionStart) + 2; + linkJumpT4(ptr, to); + cacheFlush(ptr - 2, sizeof(uint16_t) * 2); + } else { + uint16_t* ptr = reinterpret_cast(instructionStart) + 5; + linkBX(ptr, to); + cacheFlush(ptr - 5, sizeof(uint16_t) * 5); + } +#else uint16_t* ptr = reinterpret_cast(instructionStart) + 2; - linkJumpT4(ptr, to); cacheFlush(ptr - 2, sizeof(uint16_t) * 2); +#endif } static ptrdiff_t maxJumpReplacementSize() { +#if OS(LINUX) || OS(QNX) + return 10; +#else return 4; +#endif } static void replaceWithLoad(void* instructionStart) @@ -2163,7 +2226,7 @@ public: cacheFlush(ptr, sizeof(uint16_t) * 2); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -2183,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" @@ -2204,8 +2265,32 @@ public: "svc 0x0\n" "pop {r7}\n" : - : "r" (code), "r" (reinterpret_cast(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(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) @@ -2693,8 +2778,7 @@ private: AssemblerBuffer m_buffer; } m_formatter; - Vector m_jumpsToLink; - Vector m_offsets; + Vector m_jumpsToLink; int m_indexOfLastWatchpoint; int m_indexOfTailOfLastWatchpoint; }; diff --git a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h index ee78ef84eb..95eaf7d99d 100644 --- a/src/3rdparty/masm/assembler/AbstractMacroAssembler.h +++ b/src/3rdparty/masm/assembler/AbstractMacroAssembler.h @@ -510,7 +510,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) @@ -538,6 +538,10 @@ public: void link(AbstractMacroAssembler* 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) @@ -549,6 +553,10 @@ public: void linkTo(Label label, AbstractMacroAssembler* 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 @@ -592,7 +600,7 @@ public: friend class LinkBuffer; public: - typedef Vector JumpVector; + typedef Vector JumpVector; JumpList() { } @@ -683,6 +691,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 static ptrdiff_t differenceBetween(T from, U to) { @@ -715,6 +761,10 @@ protected: WeakRandom m_randomSource; +#if ENABLE(DFG_REGISTER_ALLOCATION_VALIDATION) + Vector m_registerAllocationForOffsets; +#endif + #if ENABLE(JIT_CONSTANT_BLINDING) static bool scratchRegisterForBlinding() { return false; } static bool shouldBlindForSpecificArch(uint32_t) { return true; } diff --git a/src/3rdparty/masm/assembler/AssemblerBuffer.h b/src/3rdparty/masm/assembler/AssemblerBuffer.h index bc52801ba7..54080bdac6 100644 --- a/src/3rdparty/masm/assembler/AssemblerBuffer.h +++ b/src/3rdparty/masm/assembler/AssemblerBuffer.h @@ -65,7 +65,7 @@ namespace JSC { public: AssemblerBuffer() : m_storage(inlineCapacity) - , m_buffer(&(*m_storage.begin())) + , m_buffer(m_storage.begin()) , m_capacity(inlineCapacity) , m_index(0) { @@ -164,11 +164,11 @@ namespace JSC { m_capacity += m_capacity / 2 + extraCapacity; m_storage.grow(m_capacity); - m_buffer = &(*m_storage.begin()); + m_buffer = m_storage.begin(); } private: - Vector m_storage; + Vector m_storage; char* m_buffer; int m_capacity; int m_index; diff --git a/src/3rdparty/masm/assembler/LinkBuffer.cpp b/src/3rdparty/masm/assembler/LinkBuffer.cpp index c269157ba5..645eba5380 100644 --- a/src/3rdparty/masm/assembler/LinkBuffer.cpp +++ b/src/3rdparty/masm/assembler/LinkBuffer.cpp @@ -80,7 +80,7 @@ void LinkBuffer::linkCode(void* ownerUID, JITCompilationEffort effort) uint8_t* outData = reinterpret_cast(m_code); int readPtr = 0; int writePtr = 0; - Vector& jumpsToLink = m_assembler->jumpsToLink(); + Vector& jumpsToLink = m_assembler->jumpsToLink(); unsigned jumpCount = jumpsToLink.size(); for (unsigned i = 0; i < jumpCount; ++i) { int offset = readPtr - writePtr; diff --git a/src/3rdparty/masm/assembler/MIPSAssembler.h b/src/3rdparty/masm/assembler/MIPSAssembler.h index 026f87e52a..7f553bb9a1 100644 --- a/src/3rdparty/masm/assembler/MIPSAssembler.h +++ b/src/3rdparty/masm/assembler/MIPSAssembler.h @@ -152,6 +152,8 @@ public: typedef SegmentedVector Jumps; MIPSAssembler() + : m_indexOfLastWatchpoint(INT_MIN) + , m_indexOfTailOfLastWatchpoint(INT_MIN) { } @@ -325,7 +327,7 @@ public: emitInst(0x00000000 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | ((shamt & 0x1f) << OP_SH_SHAMT)); } - void sllv(RegisterID rd, RegisterID rt, int rs) + void sllv(RegisterID rd, RegisterID rt, RegisterID rs) { emitInst(0x00000004 | (rd << OP_SH_RD) | (rt << OP_SH_RT) | (rs << OP_SH_RS)); } @@ -527,6 +529,16 @@ public: emitInst(0x46200004 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); } + void movd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200006 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + + void negd(FPRegisterID fd, FPRegisterID fs) + { + emitInst(0x46200007 | (fd << OP_SH_FD) | (fs << OP_SH_FS)); + } + void truncwd(FPRegisterID fd, FPRegisterID fs) { emitInst(0x4620000d | (fd << OP_SH_FD) | (fs << OP_SH_FS)); @@ -619,9 +631,24 @@ public: return m_buffer.label(); } + AssemblerLabel labelForWatchpoint() + { + AssemblerLabel result = m_buffer.label(); + if (static_cast(result.m_offset) != m_indexOfLastWatchpoint) + result = label(); + m_indexOfLastWatchpoint = result.m_offset; + m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize(); + return result; + } + AssemblerLabel label() { - return m_buffer.label(); + AssemblerLabel result = m_buffer.label(); + while (UNLIKELY(static_cast(result.m_offset) < m_indexOfTailOfLastWatchpoint)) { + nop(); + result = m_buffer.label(); + } + return result; } AssemblerLabel align(int alignment) @@ -664,14 +691,24 @@ public: // Assembly helpers for moving data between fp and registers. void vmov(RegisterID rd1, RegisterID rd2, FPRegisterID rn) { +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 + mfc1(rd1, rn); + mfhc1(rd2, rn); +#else mfc1(rd1, rn); mfc1(rd2, FPRegisterID(rn + 1)); +#endif } void vmov(FPRegisterID rd, RegisterID rn1, RegisterID rn2) { +#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 + mtc1(rn1, rd); + mthc1(rn2, rd); +#else mtc1(rn1, rd); mtc1(rn2, FPRegisterID(rd + 1)); +#endif } static unsigned getCallReturnOffset(AssemblerLabel call) @@ -688,6 +725,35 @@ public: // writable region of memory; to modify the code in an execute-only execuable // pool the 'repatch' and 'relink' methods should be used. + static size_t linkDirectJump(void* code, void* to) + { + MIPSWord* insn = reinterpret_cast(reinterpret_cast(code)); + size_t ops = 0; + int32_t slotAddr = reinterpret_cast(insn) + 4; + int32_t toAddr = reinterpret_cast(to); + + if ((slotAddr & 0xf0000000) != (toAddr & 0xf0000000)) { + // lui + *insn = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((toAddr >> 16) & 0xffff); + ++insn; + // ori + *insn = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (toAddr & 0xffff); + ++insn; + // jr + *insn = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS); + ++insn; + ops = 4 * sizeof(MIPSWord); + } else { + // j + *insn = 0x08000000 | ((toAddr & 0x0fffffff) >> 2); + ++insn; + ops = 2 * sizeof(MIPSWord); + } + // nop + *insn = 0x00000000; + return ops; + } + void linkJump(AssemblerLabel from, AssemblerLabel to) { ASSERT(to.isSet()); @@ -825,29 +891,36 @@ public: #endif } - static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm) + static ptrdiff_t maxJumpReplacementSize() { - MIPSWord* insn = static_cast(instructionStart) + 1; - ASSERT((*insn & 0xfc000000) == 0x34000000); - *insn = (*insn & 0xfc1f0000) | (imm & 0xffff); - cacheFlush(insn, sizeof(MIPSWord)); + return sizeof(MIPSWord) * 4; } - static void replaceWithJump(void* instructionStart, void* to) + static void revertJumpToMove(void* instructionStart, RegisterID rt, int imm) { - MIPSWord* instruction = reinterpret_cast(instructionStart); - intptr_t jumpTo = reinterpret_cast(to); + MIPSWord* insn = static_cast(instructionStart); + size_t codeSize = 2 * sizeof(MIPSWord); // lui - instruction[0] = 0x3c000000 | (MIPSRegisters::t9 << OP_SH_RT) | ((jumpTo >> 16) & 0xffff); + *insn = 0x3c000000 | (rt << OP_SH_RT) | ((imm >> 16) & 0xffff); + ++insn; // ori - instruction[1] = 0x34000000 | (MIPSRegisters::t9 << OP_SH_RT) | (MIPSRegisters::t9 << OP_SH_RS) | (jumpTo & 0xffff); - // jr - instruction[2] = 0x00000008 | (MIPSRegisters::t9 << OP_SH_RS); - // nop - instruction[3] = 0x0; + *insn = 0x34000000 | (rt << OP_SH_RS) | (rt << OP_SH_RT) | (imm & 0xffff); + ++insn; + // if jr $t9 + if (*insn == 0x03200008) { + *insn = 0x00000000; + codeSize += sizeof(MIPSWord); + } + cacheFlush(insn, codeSize); + } - cacheFlush(instruction, sizeof(MIPSWord) * 4); + static void replaceWithJump(void* instructionStart, void* to) + { + ASSERT(!(bitwise_cast(instructionStart) & 3)); + ASSERT(!(bitwise_cast(to) & 3)); + size_t ops = linkDirectJump(instructionStart, to); + cacheFlush(instructionStart, ops); } static void replaceWithLoad(void* instructionStart) @@ -1023,6 +1096,8 @@ private: AssemblerBuffer m_buffer; Jumps m_jumps; + int m_indexOfLastWatchpoint; + int m_indexOfTailOfLastWatchpoint; }; } // namespace JSC diff --git a/src/3rdparty/masm/assembler/MacroAssembler.h b/src/3rdparty/masm/assembler/MacroAssembler.h index 3d57340f93..f74680d7fc 100644 --- a/src/3rdparty/masm/assembler/MacroAssembler.h +++ b/src/3rdparty/masm/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. } } @@ -200,6 +200,13 @@ public: } #endif +#if CPU(MIPS) + void poke(FPRegisterID src, int index = 0) + { + ASSERT(!(index & 1)); + storeDouble(src, addressForPoke(index)); + } +#endif // Backwards banches, these are currently all implemented using existing forwards branch mechanisms. void branchPtr(RelationalCondition cond, RegisterID op1, TrustedImmPtr imm, Label target) @@ -847,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 @@ -869,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. @@ -927,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. @@ -1066,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. @@ -1350,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()) { @@ -1371,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/src/3rdparty/masm/assembler/MacroAssemblerARM.h b/src/3rdparty/masm/assembler/MacroAssemblerARM.h index 527126b438..01e34c97cd 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerARM.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerARM.h @@ -152,6 +152,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 +348,7 @@ public: #else UNUSED_PARAM(src); UNUSED_PARAM(dest); - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); #endif } @@ -445,10 +451,10 @@ public: m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint8, src, address.base, address.index, static_cast(address.scale), address.offset); } - void store8(TrustedImm32 imm, void* address) + void store8(TrustedImm32 imm, const void* address) { move(TrustedImm32(reinterpret_cast(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 +485,13 @@ public: m_assembler.baseIndexTransfer32(ARMAssembler::StoreUint32, ARMRegisters::S1, address.base, address.index, static_cast(address.scale), address.offset); } - void store32(RegisterID src, void* address) + void store32(RegisterID src, const void* address) { m_assembler.ldrUniqueImmediate(ARMRegisters::S0, reinterpret_cast(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(address)); m_assembler.moveImm(imm.m_value, ARMRegisters::S1); @@ -532,9 +538,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); + move(reg1, ARMRegisters::S0); + move(reg2, reg1); + move(ARMRegisters::S0, reg2); } void signExtend32ToPtr(RegisterID src, RegisterID dest) @@ -673,9 +679,8 @@ public: m_assembler.vmov(dest1, dest2, src); } - void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID scratch) + void moveIntsToDouble(RegisterID src1, RegisterID src2, FPRegisterID dest, FPRegisterID) { - UNUSED_PARAM(scratch); m_assembler.vmov(dest, src1, src2); } @@ -886,11 +891,9 @@ public: void add32(TrustedImm32 imm, AbsoluteAddress address) { - m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast(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(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) @@ -920,11 +923,9 @@ public: void sub32(TrustedImm32 imm, AbsoluteAddress address) { - m_assembler.ldrUniqueImmediate(ARMRegisters::S1, reinterpret_cast(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(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) @@ -980,6 +981,7 @@ public: Jump branchPtrWithPatch(RelationalCondition cond, RegisterID left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { + ensureSpace(3 * sizeof(ARMWord), 2 * sizeof(ARMWord)); dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S1); Jump jump = branch32(cond, left, ARMRegisters::S1, true); return jump; @@ -988,6 +990,7 @@ public: Jump branchPtrWithPatch(RelationalCondition cond, Address left, DataLabelPtr& dataLabel, TrustedImmPtr initialRightValue = TrustedImmPtr(0)) { load32(left, ARMRegisters::S1); + ensureSpace(3 * sizeof(ARMWord), 2 * sizeof(ARMWord)); dataLabel = moveWithPatch(initialRightValue, ARMRegisters::S0); Jump jump = branch32(cond, ARMRegisters::S0, ARMRegisters::S1, true); return jump; @@ -1104,7 +1107,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); } @@ -1240,7 +1243,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 fpTemp) + void branchConvertDoubleToInt32(FPRegisterID src, RegisterID dest, JumpList& failureCases, FPRegisterID) { m_assembler.vcvt_s32_f64(ARMRegisters::SD0 << 1, src); m_assembler.vmov_arm32(dest, ARMRegisters::SD0 << 1); @@ -1310,10 +1313,10 @@ public: static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID reg, void* initialValue) { - ARMAssembler::revertJump(instructionStart.dataLocation(), reg, reinterpret_cast(initialValue) & 0xffff); + ARMAssembler::revertBranchPtrWithPatch(instructionStart.dataLocation(), reg, reinterpret_cast(initialValue) & 0xffff); } - static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel instructionStart, Address, void* initialValue) + static void revertJumpReplacementToPatchableBranchPtrWithPatch(CodeLocationLabel, Address, void*) { UNREACHABLE_FOR_PLATFORM(); } diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h index 8d7a3a69aa..81c1d7e08a 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h @@ -59,7 +59,7 @@ public: return value >= -255 && value <= 255; } - Vector& jumpsToLink() { return m_assembler.jumpsToLink(); } + Vector& jumpsToLink() { return m_assembler.jumpsToLink(); } void* unlinkedCode() { return m_assembler.unlinkedCode(); } bool canCompact(JumpType jumpType) { return m_assembler.canCompact(jumpType); } JumpLinkType computeJumpType(JumpType jumpType, const uint8_t* from, const uint8_t* to) { return m_assembler.computeJumpType(jumpType, from, to); } @@ -263,6 +263,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); @@ -1767,9 +1773,14 @@ public: return label.labelAtOffset(-twoWordOpSize * 2); } - static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID, void* initialValue) + static void revertJumpReplacementToBranchPtrWithPatch(CodeLocationLabel instructionStart, RegisterID rd, void* initialValue) { +#if OS(LINUX) || OS(QNX) + ARMv7Assembler::revertJumpTo_movT3movtcmpT2(instructionStart.dataLocation(), rd, dataTempRegister, reinterpret_cast(initialValue)); +#else + UNUSED_PARAM(rd); ARMv7Assembler::revertJumpTo_movT3(instructionStart.dataLocation(), dataTempRegister, ARMThumbImmediate::makeUInt16(reinterpret_cast(initialValue) & 0xffff)); +#endif } static CodeLocationLabel startOfPatchableBranchPtrWithPatchOnAddress(CodeLocationDataLabelPtr) diff --git a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h index 89cffb1278..c2af24060a 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h @@ -134,13 +134,6 @@ public: ASSERT_VALID_CODE_POINTER(m_value); } - template - FunctionPtr(returnType(*value)(argType1, argType2, argType3, argType4, argType5, argType6)) - : m_value((void*)value) - { - ASSERT_VALID_CODE_POINTER(m_value); - } - // MSVC doesn't seem to treat functions with different calling conventions as // different types; these methods already defined for fastcall, below. #if CALLING_CONVENTION_IS_STDCALL && !OS(WINDOWS) diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h index 3ab2553001..e18d86c5b3 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h @@ -114,6 +114,11 @@ public: m_assembler.addu(dest, dest, src); } + void add32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.addu(dest, op1, op2); + } + void add32(TrustedImm32 imm, RegisterID dest) { add32(imm, dest, dest); @@ -262,11 +267,22 @@ public: m_assembler.sw(dataTempRegister, addrTempRegister, 4); } + void and32(Address src, RegisterID dest) + { + load32(src, dataTempRegister); + and32(dataTempRegister, dest); + } + void and32(RegisterID src, RegisterID dest) { m_assembler.andInsn(dest, dest, src); } + void and32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.andInsn(dest, op1, op2); + } + void and32(TrustedImm32 imm, RegisterID dest) { if (!imm.m_value && !m_fixedWidth) @@ -283,9 +299,16 @@ public: } } - void lshift32(TrustedImm32 imm, RegisterID dest) + void and32(TrustedImm32 imm, RegisterID src, RegisterID dest) { - m_assembler.sll(dest, dest, imm.m_value); + if (!imm.m_value && !m_fixedWidth) + move(MIPSRegisters::zero, dest); + else if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) + m_assembler.andi(dest, src, imm.m_value); + else { + move(imm, immTempRegister); + m_assembler.andInsn(dest, src, immTempRegister); + } } void lshift32(RegisterID shiftAmount, RegisterID dest) @@ -293,11 +316,33 @@ public: m_assembler.sllv(dest, dest, shiftAmount); } + void lshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.sllv(dest, src, shiftAmount); + } + + void lshift32(TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + m_assembler.sllv(dest, dest, immTempRegister); + } + + void lshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + move(imm, immTempRegister); + m_assembler.sllv(dest, src, immTempRegister); + } + void mul32(RegisterID src, RegisterID dest) { m_assembler.mul(dest, dest, src); } + void mul32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.mul(dest, op1, op2); + } + void mul32(TrustedImm32 imm, RegisterID src, RegisterID dest) { if (!imm.m_value && !m_fixedWidth) @@ -348,6 +393,24 @@ public: m_assembler.orInsn(dest, dest, dataTempRegister); } + void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (!imm.m_value && !m_fixedWidth) + return; + + if (imm.m_value > 0 && imm.m_value < 65535 && !m_fixedWidth) { + m_assembler.ori(dest, src, imm.m_value); + return; + } + + /* + li dataTemp, imm + or dest, src, dataTemp + */ + move(imm, dataTempRegister); + m_assembler.orInsn(dest, src, dataTempRegister); + } + void or32(RegisterID src, AbsoluteAddress dest) { load32(dest.m_ptr, dataTempRegister); @@ -360,6 +423,11 @@ public: m_assembler.srav(dest, dest, shiftAmount); } + void rshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srav(dest, src, shiftAmount); + } + void rshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.sra(dest, dest, imm.m_value); @@ -375,16 +443,31 @@ public: m_assembler.srlv(dest, dest, shiftAmount); } + void urshift32(RegisterID src, RegisterID shiftAmount, RegisterID dest) + { + m_assembler.srlv(dest, src, shiftAmount); + } + void urshift32(TrustedImm32 imm, RegisterID dest) { m_assembler.srl(dest, dest, imm.m_value); } + void urshift32(RegisterID src, TrustedImm32 imm, RegisterID dest) + { + m_assembler.srl(dest, src, imm.m_value); + } + void sub32(RegisterID src, RegisterID dest) { m_assembler.subu(dest, dest, src); } + void sub32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.subu(dest, op1, op2); + } + void sub32(TrustedImm32 imm, RegisterID dest) { if (imm.m_value >= -32767 && imm.m_value <= 32768 @@ -495,6 +578,11 @@ public: m_assembler.xorInsn(dest, dest, src); } + void xor32(RegisterID op1, RegisterID op2, RegisterID dest) + { + m_assembler.xorInsn(dest, op1, op2); + } + void xor32(TrustedImm32 imm, RegisterID dest) { if (imm.m_value == -1) { @@ -510,6 +598,21 @@ public: m_assembler.xorInsn(dest, dest, immTempRegister); } + void xor32(TrustedImm32 imm, RegisterID src, RegisterID dest) + { + if (imm.m_value == -1) { + m_assembler.nor(dest, src, MIPSRegisters::zero); + return; + } + + /* + li immTemp, imm + xor dest, dest, immTemp + */ + move(imm, immTempRegister); + m_assembler.xorInsn(dest, src, immTempRegister); + } + void sqrtDouble(FPRegisterID src, FPRegisterID dst) { m_assembler.sqrtd(dst, src); @@ -517,7 +620,7 @@ public: void absDouble(FPRegisterID, FPRegisterID) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } ConvertibleLoadLabel convertibleLoadPtr(Address address, RegisterID dest) @@ -989,6 +1092,44 @@ public: } } + void store32(TrustedImm32 imm, BaseIndex address) + { + if (address.offset >= -32768 && address.offset <= 32767 && !m_fixedWidth) { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + sw src, address.offset(addrTemp) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + if (!imm.m_value) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, address.offset); + } + } else { + /* + sll addrTemp, address.index, address.scale + addu addrTemp, addrTemp, address.base + lui immTemp, (address.offset + 0x8000) >> 16 + addu addrTemp, addrTemp, immTemp + sw src, (address.offset & 0xffff)(at) + */ + m_assembler.sll(addrTempRegister, address.index, address.scale); + m_assembler.addu(addrTempRegister, addrTempRegister, address.base); + m_assembler.lui(immTempRegister, (address.offset + 0x8000) >> 16); + m_assembler.addu(addrTempRegister, addrTempRegister, immTempRegister); + if (!imm.m_value && !m_fixedWidth) + m_assembler.sw(MIPSRegisters::zero, addrTempRegister, address.offset); + else { + move(imm, immTempRegister); + m_assembler.sw(immTempRegister, addrTempRegister, address.offset); + } + } + } + + void store32(RegisterID src, const void* address) { /* @@ -1322,7 +1463,8 @@ public: void jump(RegisterID target) { - m_assembler.jr(target); + move(target, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); m_assembler.nop(); } @@ -1335,6 +1477,15 @@ public: m_fixedWidth = false; } + void jump(AbsoluteAddress address) + { + m_fixedWidth = true; + load32(address.m_ptr, MIPSRegisters::t9); + m_assembler.jr(MIPSRegisters::t9); + m_assembler.nop(); + m_fixedWidth = false; + } + void moveDoubleToInts(FPRegisterID src, RegisterID dest1, RegisterID dest2) { m_assembler.vmov(dest1, dest2, src); @@ -1403,6 +1554,53 @@ public: return Jump(); } + Jump branchAdd32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dataTemp, op1 + xor cmpTemp, dataTemp, op2 + bltz cmpTemp, No_overflow # diff sign bit -> no overflow + addu dest, dataTemp, op2 + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign big -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(op1, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addu(dest, dataTempRegister, op2); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + add32(op1, op2, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + add32(op1, op2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + add32(op1, op2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, RegisterID dest) { move(imm, immTempRegister); @@ -1416,6 +1614,111 @@ public: return branchAdd32(cond, immTempRegister, dest); } + Jump branchAdd32(ResultCondition cond, TrustedImm32 imm, AbsoluteAddress dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dataTemp, dest + xori cmpTemp, dataTemp, imm + bltz cmpTemp, No_overflow # diff sign bit -> no overflow + addiu dataTemp, dataTemp, imm + move dest, dataTemp + xori cmpTemp, dataTemp, imm + bgez cmpTemp, No_overflow # same sign big -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + if (imm.m_value >= -32768 && imm.m_value <= 32767 && !m_fixedWidth) { + load32(dest.m_ptr, dataTempRegister); + m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addiu(dataTempRegister, dataTempRegister, imm.m_value); + store32(dataTempRegister, dest.m_ptr); + m_assembler.xori(cmpTempRegister, dataTempRegister, imm.m_value); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + } else { + load32(dest.m_ptr, dataTempRegister); + move(imm, immTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, immTempRegister); + m_assembler.bltz(cmpTempRegister, 10); + m_assembler.addiu(dataTempRegister, dataTempRegister, immTempRegister); + store32(dataTempRegister, dest.m_ptr); + m_assembler.xori(cmpTempRegister, dataTempRegister, immTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + } + return jump(); + } + move(imm, immTempRegister); + load32(dest.m_ptr, dataTempRegister); + add32(immTempRegister, dataTempRegister); + store32(dataTempRegister, dest.m_ptr); + if (cond == Signed) { + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dataTempRegister, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) + return branchEqual(dataTempRegister, MIPSRegisters::zero); + if (cond == NonZero) + return branchNotEqual(dataTempRegister, MIPSRegisters::zero); + ASSERT(0); + return Jump(); + } + + Jump branchMul32(ResultCondition cond, RegisterID src1, RegisterID src2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + mult src, dest + mfhi dataTemp + mflo dest + sra addrTemp, dest, 31 + beq dataTemp, addrTemp, No_overflow # all sign bits (bit 63 to bit 31) are the same -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + m_assembler.mult(src1, src2); + m_assembler.mfhi(dataTempRegister); + m_assembler.mflo(dest); + m_assembler.sra(addrTempRegister, dest, 31); + m_assembler.beq(dataTempRegister, addrTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + mul32(src1, src2, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + mul32(src1, src2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + mul32(src1, src2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + Jump branchMul32(ResultCondition cond, RegisterID src, RegisterID dest) { ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); @@ -1464,8 +1767,7 @@ public: Jump branchMul32(ResultCondition cond, TrustedImm32 imm, RegisterID src, RegisterID dest) { move(imm, immTempRegister); - move(src, dest); - return branchMul32(cond, immTempRegister, dest); + return branchMul32(cond, immTempRegister, src, dest); } Jump branchSub32(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1524,8 +1826,60 @@ public: Jump branchSub32(ResultCondition cond, RegisterID src, TrustedImm32 imm, RegisterID dest) { move(imm, immTempRegister); - move(src, dest); - return branchSub32(cond, immTempRegister, dest); + return branchSub32(cond, src, immTempRegister, dest); + } + + Jump branchSub32(ResultCondition cond, RegisterID op1, RegisterID op2, RegisterID dest) + { + ASSERT((cond == Overflow) || (cond == Signed) || (cond == Zero) || (cond == NonZero)); + if (cond == Overflow) { + /* + move dataTemp, op1 + xor cmpTemp, dataTemp, op2 + bgez cmpTemp, No_overflow # same sign bit -> no overflow + subu dest, dataTemp, op2 + xor cmpTemp, dest, dataTemp + bgez cmpTemp, No_overflow # same sign bit -> no overflow + nop + b Overflow + nop + nop + nop + nop + nop + No_overflow: + */ + move(op1, dataTempRegister); + m_assembler.xorInsn(cmpTempRegister, dataTempRegister, op2); + m_assembler.bgez(cmpTempRegister, 10); + m_assembler.subu(dest, dataTempRegister, op2); + m_assembler.xorInsn(cmpTempRegister, dest, dataTempRegister); + m_assembler.bgez(cmpTempRegister, 7); + m_assembler.nop(); + return jump(); + } + if (cond == Signed) { + sub32(op1, op2, dest); + // Check if dest is negative. + m_assembler.slt(cmpTempRegister, dest, MIPSRegisters::zero); + return branchNotEqual(cmpTempRegister, MIPSRegisters::zero); + } + if (cond == Zero) { + sub32(op1, op2, dest); + return branchEqual(dest, MIPSRegisters::zero); + } + if (cond == NonZero) { + sub32(op1, op2, dest); + return branchNotEqual(dest, MIPSRegisters::zero); + } + ASSERT(0); + return Jump(); + } + + Jump branchNeg32(ResultCondition cond, RegisterID srcDest) + { + m_assembler.li(dataTempRegister, -1); + return branchMul32(cond, dataTempRegister, srcDest); } Jump branchOr32(ResultCondition cond, RegisterID src, RegisterID dest) @@ -1577,7 +1931,8 @@ public: Call call(RegisterID target) { - m_assembler.jalr(target); + move(target, MIPSRegisters::t9); + m_assembler.jalr(MIPSRegisters::t9); m_assembler.nop(); return Call(m_assembler.label(), Call::None); } @@ -1821,7 +2176,7 @@ public: lui immTemp, (address.offset + 0x8000) >> 16 addu addrTemp, addrTemp, immTemp lwc1 dest, (address.offset & 0xffff)(at) - lwc1 dest+4, (address.offset & 0xffff + 4)(at) + lwc1 dest+1, (address.offset & 0xffff + 4)(at) */ m_assembler.sll(addrTempRegister, address.index, address.scale); m_assembler.addu(addrTempRegister, addrTempRegister, address.base); @@ -2008,6 +2363,19 @@ public: #endif } + void moveDouble(FPRegisterID src, FPRegisterID dest) + { + if (src != dest || m_fixedWidth) + m_assembler.movd(dest, src); + } + + void swapDouble(FPRegisterID fr1, FPRegisterID fr2) + { + moveDouble(fr1, fpTempRegister); + moveDouble(fr2, fr1); + moveDouble(fpTempRegister, fr2); + } + void addDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.addd(dest, dest, src); @@ -2035,6 +2403,11 @@ public: m_assembler.subd(dest, dest, src); } + void subDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.subd(dest, op1, op2); + } + void subDouble(Address src, FPRegisterID dest) { loadDouble(src, fpTempRegister); @@ -2052,11 +2425,32 @@ public: m_assembler.muld(dest, dest, fpTempRegister); } + void mulDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.muld(dest, op1, op2); + } + void divDouble(FPRegisterID src, FPRegisterID dest) { m_assembler.divd(dest, dest, src); } + void divDouble(FPRegisterID op1, FPRegisterID op2, FPRegisterID dest) + { + m_assembler.divd(dest, op1, op2); + } + + void divDouble(Address src, FPRegisterID dest) + { + loadDouble(src, fpTempRegister); + m_assembler.divd(dest, dest, fpTempRegister); + } + + void negateDouble(FPRegisterID src, FPRegisterID dest) + { + m_assembler.negd(dest, src); + } + void convertInt32ToDouble(RegisterID src, FPRegisterID dest) { m_assembler.mtc1(src, fpTempRegister); @@ -2116,6 +2510,8 @@ public: Jump branchEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.beq(rs, rt, 0); m_assembler.nop(); @@ -2125,6 +2521,8 @@ public: Jump branchNotEqual(RegisterID rs, RegisterID rt) { + m_assembler.nop(); + m_assembler.nop(); m_assembler.appendJump(); m_assembler.bne(rs, rt, 0); m_assembler.nop(); @@ -2191,11 +2589,33 @@ public: // If the result is not representable as a 32 bit value, branch. // May also branch for some values that are representable in 32 bits // (specifically, in this case, INT_MAX 0x7fffffff). - Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest) + enum BranchTruncateType { BranchIfTruncateFailed, BranchIfTruncateSuccessful }; + Jump branchTruncateDoubleToInt32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0x7fffffff)); + } + + Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + return branch32(branchType == BranchIfTruncateFailed ? Equal : NotEqual, dest, TrustedImm32(0)); + } + + // Result is undefined if the value is outside of the integer range. + void truncateDoubleToInt32(FPRegisterID src, RegisterID dest) + { + m_assembler.truncwd(fpTempRegister, src); + m_assembler.mfc1(dest, fpTempRegister); + } + + // Result is undefined if src > 2^31 + void truncateDoubleToUint32(FPRegisterID src, RegisterID dest) { m_assembler.truncwd(fpTempRegister, src); m_assembler.mfc1(dest, fpTempRegister); - return branch32(Equal, dest, TrustedImm32(0x7fffffff)); } // Convert 'src' to an integer, and places the resulting 'dest'. @@ -2217,28 +2637,43 @@ public: Jump branchDoubleNonZero(FPRegisterID reg, FPRegisterID scratch) { -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mthc1(MIPSRegisters::zero, scratch); -#else - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); -#endif + m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); return branchDouble(DoubleNotEqual, reg, scratch); } Jump branchDoubleZeroOrNaN(FPRegisterID reg, FPRegisterID scratch) { -#if WTF_MIPS_ISA_REV(2) && WTF_MIPS_FP64 - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mthc1(MIPSRegisters::zero, scratch); -#else - m_assembler.mtc1(MIPSRegisters::zero, scratch); - m_assembler.mtc1(MIPSRegisters::zero, FPRegisterID(scratch + 1)); -#endif + m_assembler.vmov(scratch, MIPSRegisters::zero, MIPSRegisters::zero); return branchDouble(DoubleEqualOrUnordered, reg, scratch); } + // Invert a relational condition, e.g. == becomes !=, < becomes >=, etc. + static RelationalCondition invert(RelationalCondition cond) + { + RelationalCondition r; + if (cond == Equal) + r = NotEqual; + else if (cond == NotEqual) + r = Equal; + else if (cond == Above) + r = BelowOrEqual; + else if (cond == AboveOrEqual) + r = Below; + else if (cond == Below) + r = AboveOrEqual; + else if (cond == BelowOrEqual) + r = Above; + else if (cond == GreaterThan) + r = LessThanOrEqual; + else if (cond == GreaterThanOrEqual) + r = LessThan; + else if (cond == LessThan) + r = GreaterThanOrEqual; + else if (cond == LessThanOrEqual) + r = GreaterThan; + return r; + } + void nop() { m_assembler.nop(); @@ -2251,12 +2686,12 @@ public: static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) { - ASSERT_NOT_REACHED(); + MIPSAssembler::replaceWithJump(instructionStart.dataLocation(), destination.dataLocation()); } static ptrdiff_t maxJumpReplacementSize() { - ASSERT_NOT_REACHED(); + MIPSAssembler::maxJumpReplacementSize(); return 0; } diff --git a/src/3rdparty/masm/assembler/MacroAssemblerSH4.h b/src/3rdparty/masm/assembler/MacroAssemblerSH4.h index ef210f80cb..56fb74d45b 100644 --- a/src/3rdparty/masm/assembler/MacroAssemblerSH4.h +++ b/src/3rdparty/masm/assembler/MacroAssemblerSH4.h @@ -1533,7 +1533,7 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) void absDouble(FPRegisterID, FPRegisterID) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } Jump branchTest8(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1)) @@ -2235,12 +2235,12 @@ void or32(TrustedImm32 imm, RegisterID src, RegisterID dest) static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination) { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } static ptrdiff_t maxJumpReplacementSize() { - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); return 0; } diff --git a/src/3rdparty/masm/assembler/SH4Assembler.h b/src/3rdparty/masm/assembler/SH4Assembler.h index 39f5585be1..b7a166ea99 100644 --- a/src/3rdparty/masm/assembler/SH4Assembler.h +++ b/src/3rdparty/masm/assembler/SH4Assembler.h @@ -534,7 +534,7 @@ public: oneShortOp(getOpcodeGroup2(SHLL16_OPCODE, dst)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -584,7 +584,7 @@ public: oneShortOp(getOpcodeGroup2(SHLR16_OPCODE, dst)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -654,7 +654,7 @@ public: oneShortOp(getOpcodeGroup1(CMPGT_OPCODE, left, right)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -731,7 +731,7 @@ public: oneShortOp(getOpcodeGroup5(BF_OPCODE, label)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } @@ -751,7 +751,7 @@ public: oneShortOp(getOpcodeGroup2(BSRF_OPCODE, reg)); break; default: - ASSERT_NOT_REACHED(); + RELEASE_ASSERT_NOT_REACHED(); } } diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h index 25ff6f0a50..092e775ab5 100644 --- a/src/3rdparty/masm/assembler/X86Assembler.h +++ b/src/3rdparty/masm/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(); } } -- cgit v1.2.3