text: // Copyright 2018 the V8 project authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #ifndef V8_X64_REGISTER_X64_H_
  #define V8_X64_REGISTER_X64_H_
  
  #include "src/register.h"
  #include "src/reglist.h"
  
  namespace v8 {
  namespace internal {
  
  #define GENERAL_REGISTERS(V) \
    V(rax)                     \
    V(rcx)                     \
    V(rdx)                     \
    V(rbx)                     \
    V(rsp)                     \
    V(rbp)                     \
    V(rsi)                     \
    V(rdi)                     \
    V(r8)                      \
    V(r9)                      \
    V(r10)                     \
    V(r11)                     \
    V(r12)                     \
    V(r13)                     \
    V(r14)                     \
    V(r15)
  
  #define ALLOCATABLE_GENERAL_REGISTERS(V) \
    V(rax)                                 \
    V(rbx)                                 \
    V(rdx)                                 \
    V(rcx)                                 \
    V(rsi)                                 \
    V(rdi)                                 \
    V(r8)                                  \
    V(r9)                                  \
    V(r11)                                 \
    V(r12)                                 \
    V(r14)                                 \
    V(r15)
  
  enum RegisterCode {
  #define REGISTER_CODE(R) kRegCode_##R,
    GENERAL_REGISTERS(REGISTER_CODE)
  #undef REGISTER_CODE
        kRegAfterLast
  };
  
  class Register : public RegisterBase<Register, kRegAfterLast> {
   public:
    bool is_byte_register() const { return reg_code_ <= 3; }
    // Return the high bit of the register code as a 0 or 1.  Used often
    // when constructing the REX prefix byte.
    int high_bit() const { return reg_code_ >> 3; }
    // Return the 3 low bits of the register code.  Used when encoding registers
    // in modR/M, SIB, and opcode bytes.
    int low_bits() const { return reg_code_ & 0x7; }
  
   private:
    friend class RegisterBase<Register, kRegAfterLast>;
    explicit constexpr Register(int code) : RegisterBase(code) {}
  };
  
  ASSERT_TRIVIALLY_COPYABLE(Register);
  static_assert(sizeof(Register) == sizeof(int),
                "Register can efficiently be passed by value");
  
  #define DECLARE_REGISTER(R) \
    constexpr Register R = Register::from_code<kRegCode_##R>();
  GENERAL_REGISTERS(DECLARE_REGISTER)
  #undef DECLARE_REGISTER
  constexpr Register no_reg = Register::no_reg();
  
  constexpr int kNumRegs = 16;
  
  constexpr RegList kJSCallerSaved =
      Register::ListOf<rax, rcx, rdx,
                       rbx,  // used as a caller-saved register in JavaScript code
                       rdi   // callee function
                       >();
  
  constexpr int kNumJSCallerSaved = 5;
  
  // Number of registers for which space is reserved in safepoints.
  constexpr int kNumSafepointRegisters = 16;
  
  #ifdef _WIN64
  // Windows calling convention
  constexpr Register arg_reg_1 = rcx;
  constexpr Register arg_reg_2 = rdx;
  constexpr Register arg_reg_3 = r8;
  constexpr Register arg_reg_4 = r9;
  #else
  // AMD64 calling convention
  constexpr Register arg_reg_1 = rdi;
  constexpr Register arg_reg_2 = rsi;
  constexpr Register arg_reg_3 = rdx;
  constexpr Register arg_reg_4 = rcx;
  #endif  // _WIN64
  
  #define DOUBLE_REGISTERS(V) \
    V(xmm0)                   \
    V(xmm1)                   \
    V(xmm2)                   \
    V(xmm3)                   \
    V(xmm4)                   \
    V(xmm5)                   \
    V(xmm6)                   \
    V(xmm7)                   \
    V(xmm8)                   \
    V(xmm9)                   \
    V(xmm10)                  \
    V(xmm11)                  \
    V(xmm12)                  \
    V(xmm13)                  \
    V(xmm14)                  \
    V(xmm15)
  
  #define FLOAT_REGISTERS DOUBLE_REGISTERS
  #define SIMD128_REGISTERS DOUBLE_REGISTERS
  
  #define ALLOCATABLE_DOUBLE_REGISTERS(V) \
    V(xmm0)                               \
    V(xmm1)                               \
    V(xmm2)                               \
    V(xmm3)                               \
    V(xmm4)                               \
    V(xmm5)                               \
    V(xmm6)                               \
    V(xmm7)                               \
    V(xmm8)                               \
    V(xmm9)                               \
    V(xmm10)                              \
    V(xmm11)                              \
    V(xmm12)                              \
    V(xmm13)                              \
    V(xmm14)
  
  constexpr bool kPadArguments = false;
  constexpr bool kSimpleFPAliasing = true;
  constexpr bool kSimdMaskRegisters = false;
  
  enum DoubleRegisterCode {
  #define REGISTER_CODE(R) kDoubleCode_##R,
    DOUBLE_REGISTERS(REGISTER_CODE)
  #undef REGISTER_CODE
        kDoubleAfterLast
  };
  
  class XMMRegister : public RegisterBase<XMMRegister, kDoubleAfterLast> {
   public:
    // Return the high bit of the register code as a 0 or 1.  Used often
    // when constructing the REX prefix byte.
    int high_bit() const { return reg_code_ >> 3; }
    // Return the 3 low bits of the register code.  Used when encoding registers
    // in modR/M, SIB, and opcode bytes.
    int low_bits() const { return reg_code_ & 0x7; }
  
   private:
    friend class RegisterBase<XMMRegister, kDoubleAfterLast>;
    explicit constexpr XMMRegister(int code) : RegisterBase(code) {}
  };
  
  ASSERT_TRIVIALLY_COPYABLE(XMMRegister);
  static_assert(sizeof(XMMRegister) == sizeof(int),
                "XMMRegister can efficiently be passed by value");
  
  typedef XMMRegister FloatRegister;
  
  typedef XMMRegister DoubleRegister;
  
  typedef XMMRegister Simd128Register;
  
  #define DECLARE_REGISTER(R) \
    constexpr DoubleRegister R = DoubleRegister::from_code<kDoubleCode_##R>();
  DOUBLE_REGISTERS(DECLARE_REGISTER)
  #undef DECLARE_REGISTER
  constexpr DoubleRegister no_dreg = DoubleRegister::no_reg();
  
  // Define {RegisterName} methods for the register types.
  DEFINE_REGISTER_NAMES(Register, GENERAL_REGISTERS)
  DEFINE_REGISTER_NAMES(XMMRegister, DOUBLE_REGISTERS)
  
  // Give alias names to registers for calling conventions.
  constexpr Register kReturnRegister0 = rax;
  constexpr Register kReturnRegister1 = rdx;
  constexpr Register kReturnRegister2 = r8;
  constexpr Register kJSFunctionRegister = rdi;
  constexpr Register kContextRegister = rsi;
  constexpr Register kAllocateSizeRegister = rdx;
  constexpr Register kSpeculationPoisonRegister = r12;
  constexpr Register kInterpreterAccumulatorRegister = rax;
  constexpr Register kInterpreterBytecodeOffsetRegister = r9;
  constexpr Register kInterpreterBytecodeArrayRegister = r14;
  constexpr Register kInterpreterDispatchTableRegister = r15;
  
  constexpr Register kJavaScriptCallArgCountRegister = rax;
  constexpr Register kJavaScriptCallCodeStartRegister = rcx;
  constexpr Register kJavaScriptCallTargetRegister = kJSFunctionRegister;
  constexpr Register kJavaScriptCallNewTargetRegister = rdx;
  constexpr Register kJavaScriptCallExtraArg1Register = rbx;
  
  constexpr Register kRuntimeCallFunctionRegister = rbx;
  constexpr Register kRuntimeCallArgCountRegister = rax;
  constexpr Register kRuntimeCallArgvRegister = r15;
  constexpr Register kWasmInstanceRegister = rsi;
  
  // Default scratch register used by MacroAssembler (and other code that needs
  // a spare register). The register isn't callee save, and not used by the
  // function calling convention.
  constexpr Register kScratchRegister = r10;
  constexpr XMMRegister kScratchDoubleReg = xmm15;
  constexpr Register kRootRegister = r13;  // callee save
  
  constexpr Register kOffHeapTrampolineRegister = kScratchRegister;
  
  }  // namespace internal
  }  // namespace v8
  
  #endif  // V8_X64_REGISTER_X64_H_
  