#ifndef DFGGPRInfo_h
#define DFGGPRInfo_h
#if ENABLE(DFG_JIT)
#include <assembler/MacroAssembler.h>
#include <dfg/DFGRegisterBank.h>
namespace JSC { namespace DFG {
typedef MacroAssembler::RegisterID GPRReg;
#define InvalidGPRReg ((GPRReg)-1)
#if USE(JSVALUE64)
class JSValueRegs {
public:
JSValueRegs()
: m_gpr(InvalidGPRReg)
{
}
explicit JSValueRegs(GPRReg gpr)
: m_gpr(gpr)
{
}
bool operator!() const { return m_gpr == InvalidGPRReg; }
GPRReg gpr() 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
#if USE(JSVALUE32_64)
class JSValueRegs {
public:
JSValueRegs()
: m_tagGPR(static_cast<int8_t>(InvalidGPRReg))
, m_payloadGPR(static_cast<int8_t>(InvalidGPRReg))
{
}
JSValueRegs(GPRReg tagGPR, GPRReg payloadGPR)
: m_tagGPR(tagGPR)
, m_payloadGPR(payloadGPR)
{
ASSERT((static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg) == (static_cast<GPRReg>(payloadGPR) == InvalidGPRReg));
}
bool operator!() const { return static_cast<GPRReg>(m_tagGPR) == InvalidGPRReg; }
GPRReg tagGPR() const { return static_cast<GPRReg>(m_tagGPR); }
GPRReg payloadGPR() const { return static_cast<GPRReg>(m_payloadGPR); }
private:
int8_t m_tagGPR;
int8_t m_payloadGPR;
};
class JSValueSource {
public:
JSValueSource()
: m_offset(notAddress())
, m_baseOrTag(static_cast<int8_t>(InvalidGPRReg))
, m_payload(static_cast<int8_t>(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<int8_t>(tagGPR))
, m_payload(static_cast<int8_t>(payloadGPR))
, m_tagType(0)
{
}
JSValueSource(MacroAssembler::Address address)
: m_offset(address.offset)
, m_baseOrTag(static_cast<int8_t>(address.base))
, m_payload(static_cast<int8_t>(InvalidGPRReg))
, m_tagType(0)
{
ASSERT(m_offset != notAddress());
ASSERT(static_cast<GPRReg>(m_baseOrTag) != InvalidGPRReg);
}
static JSValueSource unboxedCell(GPRReg payloadGPR)
{
JSValueSource result;
result.m_offset = notAddress();
result.m_baseOrTag = static_cast<int8_t>(InvalidGPRReg);
result.m_payload = static_cast<int8_t>(payloadGPR);
result.m_tagType = static_cast<int8_t>(JSValue::CellTag);
return result;
}
bool operator!() const { return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg && static_cast<GPRReg>(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<GPRReg>(m_baseOrTag);
}
GPRReg tagGPR() const
{
ASSERT(!isAddress() && m_baseOrTag != InvalidGPRReg);
return static_cast<GPRReg>(m_baseOrTag);
}
GPRReg payloadGPR() const
{
ASSERT(!isAddress());
return static_cast<GPRReg>(m_payload);
}
bool hasKnownTag() const
{
ASSERT(!!*this);
ASSERT(!isAddress());
return static_cast<GPRReg>(m_baseOrTag) == InvalidGPRReg;
}
uint32_t tag() const
{
return static_cast<int32_t>(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; };
#endif
#if CPU(X86)
#define NUMBER_OF_ARGUMENT_REGISTERS 0
class GPRInfo {
public:
typedef GPRReg RegisterType;
static const unsigned numberOfRegisters = 5;
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::esi;
static const GPRReg cachedResultRegister = regT0;
static const GPRReg cachedResultRegister2 = regT1;
static const GPRReg callFrameRegister = X86Registers::edi;
static const GPRReg argumentGPR0 = X86Registers::ecx; static const GPRReg argumentGPR1 = X86Registers::edx; static const GPRReg returnValueGPR = X86Registers::eax; static const GPRReg returnValueGPR2 = X86Registers::edx; static const GPRReg nonPreservedNonReturnGPR = X86Registers::ecx;
static GPRReg toRegister(unsigned index)
{
ASSERT(index < numberOfRegisters);
static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4 };
return registerForIndex[index];
}
static unsigned toIndex(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 8);
static const unsigned indexForRegister[8] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 4, InvalidIndex };
unsigned result = indexForRegister[reg];
ASSERT(result != InvalidIndex);
return result;
}
static const char* debugName(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 8);
static const char* nameForRegister[8] = {
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
};
return nameForRegister[reg];
}
private:
static const unsigned InvalidIndex = 0xffffffff;
};
#endif
#if CPU(X86_64)
#define NUMBER_OF_ARGUMENT_REGISTERS 6
class GPRInfo {
public:
typedef GPRReg RegisterType;
static const unsigned numberOfRegisters = 9;
static const GPRReg cachedResultRegister = X86Registers::eax;
static const GPRReg timeoutCheckRegister = X86Registers::r12;
static const GPRReg callFrameRegister = X86Registers::r13;
static const GPRReg tagTypeNumberRegister = X86Registers::r14;
static const GPRReg tagMaskRegister = X86Registers::r15;
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;
static const GPRReg regT6 = X86Registers::r8;
static const GPRReg regT7 = X86Registers::r9;
static const GPRReg regT8 = X86Registers::r10;
static const GPRReg argumentGPR0 = X86Registers::edi; static const GPRReg argumentGPR1 = X86Registers::esi; static const GPRReg argumentGPR2 = X86Registers::edx; static const GPRReg argumentGPR3 = X86Registers::ecx; static const GPRReg argumentGPR4 = X86Registers::r8; static const GPRReg argumentGPR5 = X86Registers::r9; static const GPRReg returnValueGPR = X86Registers::eax; static const GPRReg returnValueGPR2 = X86Registers::edx; static const GPRReg nonPreservedNonReturnGPR = X86Registers::esi;
static GPRReg toRegister(unsigned index)
{
ASSERT(index < numberOfRegisters);
static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7, regT8 };
return registerForIndex[index];
}
static unsigned toIndex(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 16);
static const unsigned indexForRegister[16] = { 0, 2, 1, 3, InvalidIndex, InvalidIndex, 5, 4, 6, 7, 8, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
unsigned result = indexForRegister[reg];
ASSERT(result != InvalidIndex);
return result;
}
static const char* debugName(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 16);
static const char* nameForRegister[16] = {
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15"
};
return nameForRegister[reg];
}
private:
static const unsigned InvalidIndex = 0xffffffff;
};
#endif
#if CPU(ARM_THUMB2)
#define NUMBER_OF_ARGUMENT_REGISTERS 4
class GPRInfo {
public:
typedef GPRReg RegisterType;
static const unsigned numberOfRegisters = 8;
static const GPRReg regT0 = ARMRegisters::r0;
static const GPRReg regT1 = ARMRegisters::r1;
static const GPRReg regT2 = ARMRegisters::r2;
static const GPRReg regT3 = ARMRegisters::r4;
static const GPRReg regT4 = ARMRegisters::r8;
static const GPRReg regT5 = ARMRegisters::r9;
static const GPRReg regT6 = ARMRegisters::r10;
static const GPRReg regT7 = ARMRegisters::r11;
static const GPRReg cachedResultRegister = regT0;
static const GPRReg cachedResultRegister2 = regT1;
static const GPRReg callFrameRegister = ARMRegisters::r5;
static const GPRReg argumentGPR0 = ARMRegisters::r0; static const GPRReg argumentGPR1 = ARMRegisters::r1; static const GPRReg argumentGPR2 = ARMRegisters::r2; static const GPRReg argumentGPR3 = ARMRegisters::r3; static const GPRReg returnValueGPR = ARMRegisters::r0; static const GPRReg returnValueGPR2 = ARMRegisters::r1; static const GPRReg nonPreservedNonReturnGPR = ARMRegisters::r2;
static GPRReg toRegister(unsigned index)
{
ASSERT(index < numberOfRegisters);
static const GPRReg registerForIndex[numberOfRegisters] = { regT0, regT1, regT2, regT3, regT4, regT5, regT6, regT7 };
return registerForIndex[index];
}
static unsigned toIndex(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 16);
static const unsigned indexForRegister[16] = { 0, 1, 2, InvalidIndex, 3, InvalidIndex, InvalidIndex, InvalidIndex, 4, 5, 6, 7, InvalidIndex, InvalidIndex, InvalidIndex, InvalidIndex };
unsigned result = indexForRegister[reg];
ASSERT(result != InvalidIndex);
return result;
}
static const char* debugName(GPRReg reg)
{
ASSERT(reg != InvalidGPRReg);
ASSERT(reg < 16);
static const char* nameForRegister[16] = {
"r0", "r1", "r2", "r3",
"r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15"
};
return nameForRegister[reg];
}
private:
static const unsigned InvalidIndex = 0xffffffff;
};
#endif
typedef RegisterBank<GPRInfo>::iterator gpr_iterator;
} }
#endif
#endif