text: //===-- EmulateInstructionARM64.h ------------------------------------*- C++ -*-===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  
  #ifndef EmulateInstructionARM64_h_
  #define EmulateInstructionARM64_h_
  
  #include "lldb/Core/EmulateInstruction.h"
  #include "lldb/Core/Error.h"
  #include "lldb/Interpreter/OptionValue.h"
  #include "Plugins/Process/Utility/ARMDefines.h"
  
  class EmulateInstructionARM64 : public lldb_private::EmulateInstruction
  {
  public: 
      static void
      Initialize ();
      
      static void
      Terminate ();
  
      static lldb_private::ConstString
      GetPluginNameStatic ();
      
      static const char *
      GetPluginDescriptionStatic ();
      
      static lldb_private::EmulateInstruction *
      CreateInstance (const lldb_private::ArchSpec &arch, 
                      lldb_private::InstructionType inst_type);
      
      static bool
      SupportsEmulatingInstructionsOfTypeStatic (lldb_private::InstructionType inst_type)
      {
          switch (inst_type)
          {
              case lldb_private::eInstructionTypeAny:
              case lldb_private::eInstructionTypePrologueEpilogue:
                  return true;
  
              case lldb_private::eInstructionTypePCModifying:
              case lldb_private::eInstructionTypeAll:
                  return false;
          }
          return false;
      }
  
      virtual lldb_private::ConstString
      GetPluginName();
  
      virtual lldb_private::ConstString
      GetShortPluginName()
      {
          return GetPluginNameStatic();
      }
  
      virtual uint32_t
      GetPluginVersion()
      {
          return 1;
      }
  
      bool
      SetTargetTriple (const lldb_private::ArchSpec &arch);
      
      EmulateInstructionARM64 (const lldb_private::ArchSpec &arch) :
          EmulateInstruction (arch),
          m_opcode_pstate (),
          m_emulated_pstate (),
          m_ignore_conditions (false)
      {
      }
  
      virtual bool
      SupportsEmulatingInstructionsOfType (lldb_private::InstructionType inst_type)
      {
          return SupportsEmulatingInstructionsOfTypeStatic (inst_type);
      }
  
      virtual bool 
      ReadInstruction ();
      
      virtual bool
      EvaluateInstruction (uint32_t evaluate_options);
      
      virtual bool
      TestEmulation (lldb_private::Stream *out_stream, 
                     lldb_private::ArchSpec &arch, 
                     lldb_private::OptionValueDictionary *test_data)
      {
          return false;
      }
  
      virtual bool
      GetRegisterInfo (lldb::RegisterKind reg_kind,
                       uint32_t reg_num, 
                       lldb_private::RegisterInfo &reg_info);
  
      virtual bool
      CreateFunctionEntryUnwind (lldb_private::UnwindPlan &unwind_plan);
  
      
      typedef enum 
      {
          AddrMode_OFF, 
          AddrMode_PRE, 
          AddrMode_POST
      } AddrMode;
      
      typedef enum 
      {
          BranchType_CALL, 
          BranchType_ERET, 
          BranchType_DRET, 
          BranchType_RET, 
          BranchType_JMP
      } BranchType;
      
      typedef enum
      {
          CountOp_CLZ, 
          CountOp_CLS, 
          CountOp_CNT
      }  CountOp;
      
      typedef enum
      {
          RevOp_RBIT, 
          RevOp_REV16, 
          RevOp_REV32, 
          RevOp_REV64
      } RevOp;
      
      typedef enum 
      {
          BitwiseOp_NOT, 
          BitwiseOp_RBIT
      } BitwiseOp;
      
  
      typedef enum
      {
          EL0 = 0,
          EL1 = 1, 
          EL2 = 2,
          EL3 = 3
      } ExceptionLevel;
      
      typedef enum 
      {
          ExtendType_SXTB, 
          ExtendType_SXTH, 
          ExtendType_SXTW, 
          ExtendType_SXTX,
          ExtendType_UXTB, 
          ExtendType_UXTH, 
          ExtendType_UXTW, 
          ExtendType_UXTX
      } ExtendType;
      
      typedef enum 
      {
          ExtractType_LEFT, 
          ExtractType_RIGHT
      } ExtractType;
      
      typedef enum 
      {
          LogicalOp_AND, 
          LogicalOp_EOR, 
          LogicalOp_ORR
      } LogicalOp;
      
      typedef enum 
      {
          MemOp_LOAD, 
          MemOp_STORE, 
          MemOp_PREFETCH, 
          MemOp_NOP
      } MemOp;
      
      typedef enum 
      {
          MoveWideOp_N, 
          MoveWideOp_Z, 
          MoveWideOp_K
      } MoveWideOp;
      
      typedef enum {
          ShiftType_LSL, 
          ShiftType_LSR, 
          ShiftType_ASR, 
          ShiftType_ROR
      } ShiftType;
  
      typedef enum 
      {
          SP0 = 0,
          SPx = 1
      } StackPointerSelection;
      
      typedef enum 
      {
          Unpredictable_WBOVERLAP, 
          Unpredictable_LDPOVERLAP
      } Unpredictable;
      
      typedef enum
      {
          Constraint_NONE, 
          Constraint_UNKNOWN, 
          Constraint_SUPPRESSWB, 
          Constraint_NOP
      } ConstraintType;
      
      typedef enum
      {
          AccType_NORMAL, 
          AccType_UNPRIV, 
          AccType_STREAM,
          AccType_ALIGNED, 
          AccType_ORDERED
      } AccType;
  
      typedef struct
      {
          uint32_t
              N:1,
              V:1,
              C:1,
              Z:1,   // condition code flags – can also be accessed as PSTATE.[N,Z,C,V]
              Q:1,   // AArch32 only – CSPR.Q bit
              IT:8,  // AArch32 only – CPSR.IT bits
              J:1,   // AArch32 only – CSPR.J bit
              T:1,   // AArch32 only – CPSR.T bit
              SS:1,  // Single step process state bit
              IL:1,  // Illegal state bit
              D:1,
              A:1,
              I:1,
              F:1,   // Interrupt masks – can also be accessed as PSTATE.[D,A,I,F]
              E:1,   // AArch32 only – CSPR.E bit
              M:5,   // AArch32 only – mode encodings
              RW:1,  // Current register width – 0 is AArch64, 1 is AArch32
              EL:2,  // Current exception level (see ExceptionLevel enum)
              SP:1;  // AArch64 only - Stack Pointer selection (see StackPointerSelection enum)
      } ProcState;
  
  protected:
  
      typedef struct
      {
          uint32_t mask;
          uint32_t value;
          uint32_t vfp_variants;
          bool (EmulateInstructionARM64::*callback) (const uint32_t opcode);
          const char *name;
      }  Opcode;
      
      static Opcode*
      GetOpcodeForInstruction (const uint32_t opcode);
  
      uint32_t
      GetFramePointerRegisterNumber() const;
  
      bool
      BranchTo (const Context &context, uint32_t N, lldb::addr_t target);
  
      bool
      ConditionHolds (const uint32_t cond, bool *is_conditional = nullptr);
  
      bool
      UsingAArch32 ();
  
      bool
      Emulate_addsub_imm (const uint32_t opcode);
  
      bool
      Emulate_ldstpair_off (const uint32_t opcode);
  
      bool
      Emulate_ldstpair_pre (const uint32_t opcode);
  
      bool
      Emulate_ldstpair_post (const uint32_t opcode);
  
      bool
      Emulate_ldstpair (const uint32_t opcode, AddrMode a_mode);
  
      bool
      EmulateB (const uint32_t opcode);
  
      bool
      EmulateBcond (const uint32_t opcode);
  
      bool
      EmulateCBZ (const uint32_t opcode);
  
      bool
      EmulateTBZ (const uint32_t opcode);
  
      ProcState m_opcode_pstate;
      ProcState m_emulated_pstate; // This can get updated by the opcode.
      bool m_ignore_conditions;
  };
  
  #endif  // EmulateInstructionARM64_h_
  