/*
* Copyright (C) 2011, 2013 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.
*/
#ifndef GPRInfo_h
#define GPRInfo_h
#include "MacroAssembler.h"
#include
namespace JSC {
typedef MacroAssembler::RegisterID GPRReg;
#define InvalidGPRReg ((::JSC::GPRReg)-1)
#if ENABLE(JIT)
#if USE(JSVALUE64)
class JSValueRegs {
public:
JSValueRegs()
: m_gpr(InvalidGPRReg)
{
}
explicit JSValueRegs(GPRReg gpr)
: m_gpr(gpr)
{
}
static JSValueRegs payloadOnly(GPRReg gpr)
{
return JSValueRegs(gpr);
}
bool operator!() const { return m_gpr == InvalidGPRReg; }
GPRReg gpr() const { return m_gpr; }
GPRReg tagGPR() const { return InvalidGPRReg; }
GPRReg payloadGPR() const { return m_gpr; }
private:
GPRReg m_gpr;
};
class JSValueSource {
public:
JSValueSource()
: m_offset(notAddress())
, m_base(InvalidGPRReg)
{
}
JSValueSource(JSValueRegs regs)
: m_offset(notAddress())
, m_base(regs.gpr())
{
}
explicit JSValueSource(GPRReg gpr)
: m_offset(notAddress())
, m_base(gpr)
{
}
JSValueSource(MacroAssembler::Address address)
: m_offset(address.offset)
, m_base(address.base)
{
ASSERT(m_offset != notAddress());
ASSERT(m_base != InvalidGPRReg);
}
static JSValueSource unboxedCell(GPRReg payloadGPR)
{
return JSValueSource(payloadGPR);
}
bool operator!() const { return m_base == InvalidGPRReg; }
bool isAddress() const { return m_offset != notAddress(); }
int32_t offset() const
{
ASSERT(isAddress());
return m_offset;
}
GPRReg base() const
{
ASSERT(isAddress());
return m_base;
}
GPRReg gpr() const
{
ASSERT(!isAddress());
return m_base;
}
MacroAssembler::Address asAddress() const { return MacroAssembler::Address(base(), offset()); }
private:
static inline int32_t notAddress() { return 0x80000000; }
int32_t m_offset;
GPRReg m_base;
};
#endif // USE(JSVALUE64)
#if USE(JSVALUE32_64)
class JSValueRegs {
public:
JSValueRegs()
: m_tagGPR(static_cast(InvalidGPRReg))
, m_payloadGPR(static_cast(InvalidGPRReg))
{
}
JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
: m_tagGPR(tagGPR)
, m_payloadGPR(payloadGPR)
{
}
static JSValueRegs payloadOnly(GPRReg gpr)
{
return JSValueRegs(InvalidGPRReg, gpr);
}
bool operator!() const
{
return static_cast(m_tagGPR) == InvalidGPRReg
&& static_cast(m_payloadGPR) == InvalidGPRReg;
}
GPRReg tagGPR() const { return static_cast(m_tagGPR); }
GPRReg payloadGPR() const { return static_cast(m_payloadGPR); }
GPRReg gpr(WhichValueWord which) const
{
switch (which) {
case TagWord:
return tagGPR();
case PayloadWord:
return payloadGPR();
}
ASSERT_NOT_REACHED();
return tagGPR();
}
private:
int8_t m_tagGPR;
int8_t m_payloadGPR;
};
class JSValueSource {
public:
JSValueSource()
: m_offset(notAddress())
, m_baseOrTag(static_cast(InvalidGPRReg))
, m_payload(static_cast(InvalidGPRReg))
, m_tagType(0)
{
}
JSValueSource(JSValueRegs regs)
: m_offset(notAddress())
, m_baseOrTag(regs.tagGPR())
, m_payload(regs.payloadGPR())
, m_tagType(0)
{
}
JSValueSource(GPRReg tagGPR, GPRReg payloadGPR)
: m_offset(notAddress())
, m_baseOrTag(static_cast(tagGPR))
, m_payload(static_cast(payloadGPR))
, m_tagType(0)
{
}
JSValueSource(MacroAssembler::Address address)
: m_offset(address.offset)
, m_baseOrTag(static_cast(address.base))
, m_payload(static_cast(InvalidGPRReg))
, m_tagType(0)
{
ASSERT(m_offset != notAddress());
ASSERT(static_cast(m_baseOrTag) != InvalidGPRReg);
}
static JSValueSource unboxedCell(GPRReg payloadGPR)
{
JSValueSource result;
result.m_offset = notAddress();
result.m_baseOrTag = static_cast(InvalidGPRReg);
result.m_payload = static_cast(payloadGPR);
result.m_tagType = static_cast(JSValue::CellTag);
return result;
}
bool operator!() const
{
return static_cast(m_baseOrTag) == InvalidGPRReg
&& static_cast(m_payload) == InvalidGPRReg;
}
bool isAddress() const
{
ASSERT(!!*this);
return m_offset != notAddress();
}
int32_t offset() const
{
ASSERT(isAddress());
return m_offset;
}
GPRReg base() const
{
ASSERT(isAddress());
return static_cast(m_baseOrTag);
}
GPRReg tagGPR() const
{
ASSERT(!isAddress() && static_cast(m_baseOrTag) != InvalidGPRReg);
return static_cast(m_baseOrTag);
}
GPRReg payloadGPR() const
{
ASSERT(!isAddress());
return static_cast(m_payload);
}
bool hasKnownTag() const
{
ASSERT(!!*this);
ASSERT(!isAddress());
return static_cast(m_baseOrTag) == InvalidGPRReg;
}
uint32_t tag() const
{
return static_cast(m_tagType);
}
MacroAssembler::Address asAddress(unsigned additionalOffset = 0) const { return MacroAssembler::Address(base(), offset() + additionalOffset); }
private:
static inline int32_t notAddress() { return 0x80000000; }
int32_t m_offset;
int8_t m_baseOrTag;
int8_t m_payload;
int8_t m_tagType; // Contains the low bits of the tag.
};
#endif // USE(JSVALUE32_64)
// The baseline JIT requires that regT3 be callee-preserved.
#if CPU(X86)
#define NUMBER_OF_ARGUMENT_REGISTERS 0u
class GPRInfo {
public:
typedef GPRReg RegisterType;
static const unsigned numberOfRegisters = 6;
static const unsigned numberOfArgumentRegisters = NUMBER_OF_ARGUMENT_REGISTERS;
// Note: regT3 is required to be callee-preserved.
// Temporary registers.
static const GPRReg regT0 = X86Registers::eax;
static const GPRReg regT1 = X86Registers::edx;
static const GPRReg regT2 = X86Registers::ecx;
static const GPRReg regT3 = X86Registers::ebx;
static const GPRReg regT4 = X86Registers::edi;
static const GPRReg regT5 = X86Registers::esi;
// These registers match the baseline JIT.
static const GPRReg cachedResultRegister = regT0;
static const GPRReg cachedResultRegister2 = regT1;
static const GPRReg callFrameRegister = X86Registers::ebp;
// These constants provide the names for the general purpose argument & return value registers.
static const GPRReg argumentGPR0 = X86Registers::ecx; // regT2
static const GPRReg argumentGPR1 = X86Registers::edx; // regT1
static const GPRReg nonArgGPR0 = X86Registers::esi; // regT4
static const GPRReg nonArgGPR1 = X86Registers::eax; // regT0
static const GPRReg nonArgGPR2 = X86Registers::ebx; // regT3
static const GPRReg returnValueGPR = X86Registers::eax; // regT0
static const GPRReg returnValueGPR2 = X86Registers::edx; // regT1
static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
static GPRReg toRegister(unsigned index)
{
ASSERT(index (reg) (reg) (reg) (reg) (reg) (reg) (reg) != InvalidGPRReg);
ASSERT(static_cast(reg)