/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * 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/Assertions.h" #include #include #include namespace js { namespace jit { namespace X86Encoding { enum RegisterID : uint8_t { 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) < std::size(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) < std::size(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) < std::size(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) < std::size(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) < std::size(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 < std::size(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) < std::size(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 ROUNDSS / ROUNDSD. enum RoundingMode { RoundToNearest = 0x0, RoundDown = 0x1, RoundUp = 0x2, RoundToZero = 0x3 }; // Rounding modes for ROUNDPS / ROUNDPD. Note these are the same as for // RoundingMode above but incorporate the 'inexact' bit which says not to signal // exceptions for lost precision. It's not obvious that this bit is needed; it // was however suggested in the wasm SIMD proposal that led to these encodings. enum class SSERoundingMode { RoundToNearest = 0x08, RoundDown = 0x09, RoundUp = 0x0A, RoundToZero = 0x0B }; // 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(address); int32_t immediate = static_cast(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(reinterpret_cast(address)); } } // namespace X86Encoding } // namespace jit } // namespace js #endif /* jit_x86_shared_Constants_x86_shared_h */