summaryrefslogtreecommitdiff
path: root/Source/JavaScriptCore/assembler
diff options
context:
space:
mode:
Diffstat (limited to 'Source/JavaScriptCore/assembler')
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.cpp4
-rw-r--r--Source/JavaScriptCore/assembler/ARMAssembler.h83
-rw-r--r--Source/JavaScriptCore/assembler/ARMv7Assembler.h99
-rw-r--r--Source/JavaScriptCore/assembler/AbstractMacroAssembler.h86
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBuffer.h8
-rw-r--r--Source/JavaScriptCore/assembler/AssemblerBufferWithConstantPool.h4
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.cpp6
-rw-r--r--Source/JavaScriptCore/assembler/LinkBuffer.h8
-rw-r--r--Source/JavaScriptCore/assembler/MIPSAssembler.h4
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssembler.h34
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARM.h82
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerARMv7.h14
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerCodeRef.h1
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerMIPS.h69
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerSH4.cpp52
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerSH4.h1404
-rw-r--r--Source/JavaScriptCore/assembler/MacroAssemblerX86Common.h6
-rw-r--r--Source/JavaScriptCore/assembler/SH4Assembler.h289
-rw-r--r--Source/JavaScriptCore/assembler/X86Assembler.h12
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(); }