//===-- ARM64_DWARF_Registers.cpp -------------------------------*- C++ -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include <string.h>

#include "ARM64_DWARF_Registers.h"

using namespace lldb;
using namespace lldb_private;
using namespace arm64_dwarf;

const char *arm64_dwarf::GetRegisterName(unsigned reg_num,
                                         bool altnernate_name) {
  if (altnernate_name) {
    switch (reg_num) {
    case fp:
      return "x29";
    case lr:
      return "x30";
    case sp:
      return "x31";
    default:
      break;
    }
    return nullptr;
  }

  switch (reg_num) {
  case x0:
    return "x0";
  case x1:
    return "x1";
  case x2:
    return "x2";
  case x3:
    return "x3";
  case x4:
    return "x4";
  case x5:
    return "x5";
  case x6:
    return "x6";
  case x7:
    return "x7";
  case x8:
    return "x8";
  case x9:
    return "x9";
  case x10:
    return "x10";
  case x11:
    return "x11";
  case x12:
    return "x12";
  case x13:
    return "x13";
  case x14:
    return "x14";
  case x15:
    return "x15";
  case x16:
    return "x16";
  case x17:
    return "x17";
  case x18:
    return "x18";
  case x19:
    return "x19";
  case x20:
    return "x20";
  case x21:
    return "x21";
  case x22:
    return "x22";
  case x23:
    return "x23";
  case x24:
    return "x24";
  case x25:
    return "x25";
  case x26:
    return "x26";
  case x27:
    return "x27";
  case x28:
    return "x28";
  case fp:
    return "fp";
  case lr:
    return "lr";
  case sp:
    return "sp";
  case pc:
    return "pc";
  case cpsr:
    return "cpsr";
  case v0:
    return "v0";
  case v1:
    return "v1";
  case v2:
    return "v2";
  case v3:
    return "v3";
  case v4:
    return "v4";
  case v5:
    return "v5";
  case v6:
    return "v6";
  case v7:
    return "v7";
  case v8:
    return "v8";
  case v9:
    return "v9";
  case v10:
    return "v10";
  case v11:
    return "v11";
  case v12:
    return "v12";
  case v13:
    return "v13";
  case v14:
    return "v14";
  case v15:
    return "v15";
  case v16:
    return "v16";
  case v17:
    return "v17";
  case v18:
    return "v18";
  case v19:
    return "v19";
  case v20:
    return "v20";
  case v21:
    return "v21";
  case v22:
    return "v22";
  case v23:
    return "v23";
  case v24:
    return "v24";
  case v25:
    return "v25";
  case v26:
    return "v26";
  case v27:
    return "v27";
  case v28:
    return "v28";
  case v29:
    return "v29";
  case v30:
    return "v30";
  case v31:
    return "v31";
  }
  return nullptr;
}

bool arm64_dwarf::GetRegisterInfo(unsigned reg_num, RegisterInfo &reg_info) {
  ::memset(&reg_info, 0, sizeof(RegisterInfo));
  ::memset(reg_info.kinds, LLDB_INVALID_REGNUM, sizeof(reg_info.kinds));

  if (reg_num >= x0 && reg_num <= pc) {
    reg_info.byte_size = 8;
    reg_info.format = eFormatHex;
    reg_info.encoding = eEncodingUint;
  } else if (reg_num >= v0 && reg_num <= v31) {
    reg_info.byte_size = 16;
    reg_info.format = eFormatVectorOfFloat32;
    reg_info.encoding = eEncodingVector;
  } else if (reg_num == cpsr) {
    reg_info.byte_size = 4;
    reg_info.format = eFormatHex;
    reg_info.encoding = eEncodingUint;
  } else {
    return false;
  }

  reg_info.name = arm64_dwarf::GetRegisterName(reg_num, false);
  reg_info.alt_name = arm64_dwarf::GetRegisterName(reg_num, true);
  reg_info.kinds[eRegisterKindDWARF] = reg_num;

  switch (reg_num) {
  case fp:
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
    break;
  case lr:
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
    break;
  case sp:
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
    break;
  case pc:
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
    break;
  default:
    break;
  }
  return true;
}
