blob: f3436addb8a4683ef9b6bb7a3c385171f20a737b [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef jit_x86_shared_Constants_x86_shared_h
#define jit_x86_shared_Constants_x86_shared_h
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include <stddef.h>
namespace js {
namespace jit {
namespace X86Encoding {
enum RegisterID {
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi
#ifdef JS_CODEGEN_X64
,r8, r9, r10, r11, r12, r13, r14, r15
#endif
,invalid_reg
};
enum HRegisterID {
ah = rsp,
ch = rbp,
dh = rsi,
bh = rdi
};
enum XMMRegisterID {
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
#ifdef JS_CODEGEN_X64
,xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
#endif
,invalid_xmm
};
inline const char* XMMRegName(XMMRegisterID reg)
{
static const char* const names[] = {
"%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7"
#ifdef JS_CODEGEN_X64
,"%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15"
#endif
};
MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
return names[reg];
}
#ifdef JS_CODEGEN_X64
inline const char* GPReg64Name(RegisterID reg)
{
static const char* const names[] = {
"%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi"
#ifdef JS_CODEGEN_X64
,"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
#endif
};
MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
return names[reg];
}
#endif
inline const char* GPReg32Name(RegisterID reg)
{
static const char* const names[] = {
"%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi"
#ifdef JS_CODEGEN_X64
,"%r8d", "%r9d", "%r10d", "%r11d", "%r12d", "%r13d", "%r14d", "%r15d"
#endif
};
MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
return names[reg];
}
inline const char* GPReg16Name(RegisterID reg)
{
static const char* const names[] = {
"%ax", "%cx", "%dx", "%bx", "%sp", "%bp", "%si", "%di"
#ifdef JS_CODEGEN_X64
,"%r8w", "%r9w", "%r10w", "%r11w", "%r12w", "%r13w", "%r14w", "%r15w"
#endif
};
MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
return names[reg];
}
inline const char* GPReg8Name(RegisterID reg)
{
static const char* const names[] = {
"%al", "%cl", "%dl", "%bl"
#ifdef JS_CODEGEN_X64
,"%spl", "%bpl", "%sil", "%dil",
"%r8b", "%r9b", "%r10b", "%r11b", "%r12b", "%r13b", "%r14b", "%r15b"
#endif
};
MOZ_ASSERT(size_t(reg) < mozilla::ArrayLength(names));
return names[reg];
}
inline const char* GPRegName(RegisterID reg)
{
#ifdef JS_CODEGEN_X64
return GPReg64Name(reg);
#else
return GPReg32Name(reg);
#endif
}
inline bool HasSubregL(RegisterID reg)
{
#ifdef JS_CODEGEN_X64
// In 64-bit mode, all registers have an 8-bit lo subreg.
return true;
#else
// In 32-bit mode, only the first four registers do.
return reg <= rbx;
#endif
}
inline bool HasSubregH(RegisterID reg)
{
// The first four registers always have h registers. However, note that
// on x64, h registers may not be used in instructions using REX
// prefixes. Also note that this may depend on what other registers are
// used!
return reg <= rbx;
}
inline HRegisterID GetSubregH(RegisterID reg)
{
MOZ_ASSERT(HasSubregH(reg));
return HRegisterID(reg + 4);
}
inline const char* HRegName8(HRegisterID reg)
{
static const char* const names[] = {
"%ah", "%ch", "%dh", "%bh"
};
size_t index = reg - GetSubregH(rax);
MOZ_ASSERT(index < mozilla::ArrayLength(names));
return names[index];
}
enum Condition {
ConditionO,
ConditionNO,
ConditionB,
ConditionAE,
ConditionE,
ConditionNE,
ConditionBE,
ConditionA,
ConditionS,
ConditionNS,
ConditionP,
ConditionNP,
ConditionL,
ConditionGE,
ConditionLE,
ConditionG,
ConditionC = ConditionB,
ConditionNC = ConditionAE
};
inline const char* CCName(Condition cc)
{
static const char* const names[] = {
"o ", "no", "b ", "ae", "e ", "ne", "be", "a ",
"s ", "ns", "p ", "np", "l ", "ge", "le", "g "
};
MOZ_ASSERT(size_t(cc) < mozilla::ArrayLength(names));
return names[cc];
}
// Conditions for CMP instructions (CMPSS, CMPSD, CMPPS, CMPPD, etc).
enum ConditionCmp {
ConditionCmp_EQ = 0x0,
ConditionCmp_LT = 0x1,
ConditionCmp_LE = 0x2,
ConditionCmp_UNORD = 0x3,
ConditionCmp_NEQ = 0x4,
ConditionCmp_NLT = 0x5,
ConditionCmp_NLE = 0x6,
ConditionCmp_ORD = 0x7,
};
// Rounding modes for ROUNDSD.
enum RoundingMode {
RoundToNearest = 0x0,
RoundDown = 0x1,
RoundUp = 0x2,
RoundToZero = 0x3
};
// Test whether the given address will fit in an address immediate field.
// This is always true on x86, but on x64 it's only true for addreses which
// fit in the 32-bit immediate field.
inline bool IsAddressImmediate(const void* address)
{
intptr_t value = reinterpret_cast<intptr_t>(address);
int32_t immediate = static_cast<int32_t>(value);
return value == immediate;
}
// Convert the given address to a 32-bit immediate field value. This is a
// no-op on x86, but on x64 it asserts that the address is actually a valid
// address immediate.
inline int32_t AddressImmediate(const void* address)
{
MOZ_ASSERT(IsAddressImmediate(address));
return static_cast<int32_t>(reinterpret_cast<intptr_t>(address));
}
} // namespace X86Encoding
} // namespace jit
} // namespace js
#endif /* jit_x86_shared_Constants_x86_shared_h */