namespace JSC {
class MacroAssemblerX86Common : public AbstractMacroAssembler<X86Assembler> {
-protected:
+public:
#if CPU(X86_64)
static const X86Registers::RegisterID scratchRegister = X86Registers::r11;
#endif
+protected:
static const int DoubleConditionBitInvert = 0x10;
static const int DoubleConditionBitSpecial = 0x20;
static const int DoubleConditionBits = DoubleConditionBitInvert | DoubleConditionBitSpecial;
public:
- typedef X86Assembler::FPRegisterID FPRegisterID;
typedef X86Assembler::XMMRegisterID XMMRegisterID;
static bool isCompactPtrAlignedAddressOffset(ptrdiff_t value)
DoubleConditionBits_should_not_interfere_with_X86Assembler_Condition_codes);
static const RegisterID stackPointerRegister = X86Registers::esp;
-
-#if ENABLE(JIT_CONSTANT_BLINDING)
+ static const RegisterID framePointerRegister = X86Registers::ebp;
+
+ static bool canBlind() { return true; }
static bool shouldBlindForSpecificArch(uint32_t value) { return value >= 0x00ffffff; }
-#if CPU(X86_64)
static bool shouldBlindForSpecificArch(uint64_t value) { return value >= 0x00ffffff; }
-#if OS(DARWIN) // On 64-bit systems other than DARWIN uint64_t and uintptr_t are the same type so overload is prohibited.
- static bool shouldBlindForSpecificArch(uintptr_t value) { return value >= 0x00ffffff; }
-#endif
-#endif
-#endif
// Integer arithmetic operations:
//
void add32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.addl_ir(imm.m_value, dest);
+ if (imm.m_value == 1)
+ m_assembler.inc_r(dest);
+ else
+ m_assembler.addl_ir(imm.m_value, dest);
}
void add32(Address src, RegisterID dest)
void sub32(TrustedImm32 imm, RegisterID dest)
{
- m_assembler.subl_ir(imm.m_value, dest);
+ if (imm.m_value == 1)
+ m_assembler.dec_r(dest);
+ else
+ m_assembler.subl_ir(imm.m_value, dest);
}
void sub32(TrustedImm32 imm, Address address)
{
ASSERT(src != dst);
static const double negativeZeroConstant = -0.0;
- loadDouble(&negativeZeroConstant, dst);
+ loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
m_assembler.andnpd_rr(src, dst);
}
{
ASSERT(src != dst);
static const double negativeZeroConstant = -0.0;
- loadDouble(&negativeZeroConstant, dst);
+ loadDouble(TrustedImmPtr(&negativeZeroConstant), dst);
m_assembler.xorpd_rr(src, dst);
}
ASSERT(-128 <= imm.m_value && imm.m_value < 128);
m_assembler.movb_i8m(imm.m_value, address.offset, address.base, address.index, address.scale);
}
-
+
+ static ALWAYS_INLINE RegisterID getUnusedRegister(BaseIndex address)
+ {
+ if (address.base != X86Registers::eax && address.index != X86Registers::eax)
+ return X86Registers::eax;
+
+ if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
+ return X86Registers::ebx;
+
+ ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
+ return X86Registers::ecx;
+ }
+
+ static ALWAYS_INLINE RegisterID getUnusedRegister(Address address)
+ {
+ if (address.base != X86Registers::eax)
+ return X86Registers::eax;
+
+ ASSERT(address.base != X86Registers::edx);
+ return X86Registers::edx;
+ }
+
void store8(RegisterID src, BaseIndex address)
{
#if CPU(X86)
// esp..edi are mapped to the 'h' registers!
if (src >= 4) {
// Pick a temporary register.
- RegisterID temp;
- if (address.base != X86Registers::eax && address.index != X86Registers::eax)
- temp = X86Registers::eax;
- else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
- temp = X86Registers::ebx;
- else {
- ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
- temp = X86Registers::ecx;
- }
+ RegisterID temp = getUnusedRegister(address);
// Swap to the temporary register to perform the store.
swap(src, temp);
#endif
m_assembler.movb_rm(src, address.offset, address.base, address.index, address.scale);
}
+
+ void store8(RegisterID src, Address address)
+ {
+#if CPU(X86)
+ // On 32-bit x86 we can only store from the first 4 registers;
+ // esp..edi are mapped to the 'h' registers!
+ if (src >= 4) {
+ // Pick a temporary register.
+ RegisterID temp = getUnusedRegister(address);
+
+ // Swap to the temporary register to perform the store.
+ swap(src, temp);
+ m_assembler.movb_rm(temp, address.offset, address.base);
+ swap(src, temp);
+ return;
+ }
+#endif
+ m_assembler.movb_rm(src, address.offset, address.base);
+ }
void store16(RegisterID src, BaseIndex address)
{
// esp..edi are mapped to the 'h' registers!
if (src >= 4) {
// Pick a temporary register.
- RegisterID temp;
- if (address.base != X86Registers::eax && address.index != X86Registers::eax)
- temp = X86Registers::eax;
- else if (address.base != X86Registers::ebx && address.index != X86Registers::ebx)
- temp = X86Registers::ebx;
- else {
- ASSERT(address.base != X86Registers::ecx && address.index != X86Registers::ecx);
- temp = X86Registers::ecx;
- }
-
+ RegisterID temp = getUnusedRegister(address);
+
// Swap to the temporary register to perform the store.
swap(src, temp);
m_assembler.movw_rm(temp, address.offset, address.base, address.index, address.scale);
m_assembler.movsd_rr(src, dest);
}
- void loadDouble(const void* address, FPRegisterID dest)
+ void loadDouble(TrustedImmPtr address, FPRegisterID dest)
{
#if CPU(X86)
ASSERT(isSSE2Present());
- m_assembler.movsd_mr(address, dest);
+ m_assembler.movsd_mr(address.m_value, dest);
#else
- move(TrustedImmPtr(address), scratchRegister);
+ move(address, scratchRegister);
loadDouble(scratchRegister, dest);
#endif
}
return branch32(branchType ? NotEqual : Equal, dest, TrustedImm32(0x80000000));
}
- Jump branchTruncateDoubleToUint32(FPRegisterID src, RegisterID dest, BranchTruncateType branchType = BranchIfTruncateFailed)
- {
- ASSERT(isSSE2Present());
- m_assembler.cvttsd2si_rr(src, dest);
- return branch32(branchType ? GreaterThanOrEqual : LessThan, dest, TrustedImm32(0));
- }
-
void truncateDoubleToInt32(FPRegisterID src, RegisterID dest)
{
ASSERT(isSSE2Present());
return Jump(m_assembler.jCC(x86Condition(cond)));
}
- Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
+ void test32(ResultCondition, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
{
- // if we are only interested in the low seven bits, this can be tested with a testb
if (mask.m_value == -1)
m_assembler.testl_rr(reg, reg);
- else
+ else if (!(mask.m_value & ~0xff) && reg < X86Registers::esp) { // Using esp and greater as a byte register yields the upper half of the 16 bit registers ax, cx, dx and bx, e.g. esp, register 4, is actually ah.
+ if (mask.m_value == 0xff)
+ m_assembler.testb_rr(reg, reg);
+ else
+ m_assembler.testb_i8r(mask.m_value, reg);
+ } else
m_assembler.testl_i32r(mask.m_value, reg);
+ }
+
+ Jump branch(ResultCondition cond)
+ {
return Jump(m_assembler.jCC(x86Condition(cond)));
}
+ Jump branchTest32(ResultCondition cond, RegisterID reg, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ test32(cond, reg, mask);
+ return branch(cond);
+ }
+
Jump branchTest32(ResultCondition cond, Address address, TrustedImm32 mask = TrustedImm32(-1))
{
- if (mask.m_value == -1)
- m_assembler.cmpl_im(0, address.offset, address.base);
- else
- m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
+ generateTest32(address, mask);
return Jump(m_assembler.jCC(x86Condition(cond)));
}
void test32(ResultCondition cond, Address address, TrustedImm32 mask, RegisterID dest)
{
- if (mask.m_value == -1)
- m_assembler.cmpl_im(0, address.offset, address.base);
- else
- m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
+ generateTest32(address, mask);
set32(x86Condition(cond), dest);
}
{
m_assembler.nop();
}
+
+ void memoryFence()
+ {
+ m_assembler.mfence();
+ }
static void replaceWithJump(CodeLocationLabel instructionStart, CodeLocationLabel destination)
{
return X86Assembler::maxJumpReplacementSize();
}
+#if USE(MASM_PROBE)
+ struct CPUState {
+ #define DECLARE_REGISTER(_type, _regName) \
+ _type _regName;
+ FOR_EACH_CPU_REGISTER(DECLARE_REGISTER)
+ #undef DECLARE_REGISTER
+ };
+
+ struct ProbeContext;
+ typedef void (*ProbeFunction)(struct ProbeContext*);
+
+ struct ProbeContext {
+ ProbeFunction probeFunction;
+ void* arg1;
+ void* arg2;
+ CPUState cpu;
+
+ void dump(const char* indentation = 0);
+ private:
+ void dumpCPURegisters(const char* indentation);
+ };
+#endif // USE(MASM_PROBE)
+
protected:
X86Assembler::Condition x86Condition(RelationalCondition cond)
{
// x86_64, and clients & subclasses of MacroAssembler should be using 'supportsFloatingPoint()'.
friend class MacroAssemblerX86;
+ ALWAYS_INLINE void generateTest32(Address address, TrustedImm32 mask = TrustedImm32(-1))
+ {
+ if (mask.m_value == -1)
+ m_assembler.cmpl_im(0, address.offset, address.base);
+ else if (!(mask.m_value & ~0xff))
+ m_assembler.testb_im(mask.m_value, address.offset, address.base);
+ else if (!(mask.m_value & ~0xff00))
+ m_assembler.testb_im(mask.m_value >> 8, address.offset + 1, address.base);
+ else if (!(mask.m_value & ~0xff0000))
+ m_assembler.testb_im(mask.m_value >> 16, address.offset + 2, address.base);
+ else if (!(mask.m_value & ~0xff000000))
+ m_assembler.testb_im(mask.m_value >> 24, address.offset + 3, address.base);
+ else
+ m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
+ }
+
#if CPU(X86)
#if OS(MAC_OS_X)