//===-- ARM_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 "ARM_DWARF_Registers.h"
#include <string.h>

#include <string.h>

using namespace lldb;
using namespace lldb_private;

const char *GetARMDWARFRegisterName(unsigned reg_num) {
  switch (reg_num) {
  case dwarf_r0:
    return "r0";
  case dwarf_r1:
    return "r1";
  case dwarf_r2:
    return "r2";
  case dwarf_r3:
    return "r3";
  case dwarf_r4:
    return "r4";
  case dwarf_r5:
    return "r5";
  case dwarf_r6:
    return "r6";
  case dwarf_r7:
    return "r7";
  case dwarf_r8:
    return "r8";
  case dwarf_r9:
    return "r9";
  case dwarf_r10:
    return "r10";
  case dwarf_r11:
    return "r11";
  case dwarf_r12:
    return "r12";
  case dwarf_sp:
    return "sp";
  case dwarf_lr:
    return "lr";
  case dwarf_pc:
    return "pc";
  case dwarf_cpsr:
    return "cpsr";

  case dwarf_s0:
    return "s0";
  case dwarf_s1:
    return "s1";
  case dwarf_s2:
    return "s2";
  case dwarf_s3:
    return "s3";
  case dwarf_s4:
    return "s4";
  case dwarf_s5:
    return "s5";
  case dwarf_s6:
    return "s6";
  case dwarf_s7:
    return "s7";
  case dwarf_s8:
    return "s8";
  case dwarf_s9:
    return "s9";
  case dwarf_s10:
    return "s10";
  case dwarf_s11:
    return "s11";
  case dwarf_s12:
    return "s12";
  case dwarf_s13:
    return "s13";
  case dwarf_s14:
    return "s14";
  case dwarf_s15:
    return "s15";
  case dwarf_s16:
    return "s16";
  case dwarf_s17:
    return "s17";
  case dwarf_s18:
    return "s18";
  case dwarf_s19:
    return "s19";
  case dwarf_s20:
    return "s20";
  case dwarf_s21:
    return "s21";
  case dwarf_s22:
    return "s22";
  case dwarf_s23:
    return "s23";
  case dwarf_s24:
    return "s24";
  case dwarf_s25:
    return "s25";
  case dwarf_s26:
    return "s26";
  case dwarf_s27:
    return "s27";
  case dwarf_s28:
    return "s28";
  case dwarf_s29:
    return "s29";
  case dwarf_s30:
    return "s30";
  case dwarf_s31:
    return "s31";

  // FPA Registers 0-7
  case dwarf_f0:
    return "f0";
  case dwarf_f1:
    return "f1";
  case dwarf_f2:
    return "f2";
  case dwarf_f3:
    return "f3";
  case dwarf_f4:
    return "f4";
  case dwarf_f5:
    return "f5";
  case dwarf_f6:
    return "f6";
  case dwarf_f7:
    return "f7";

  // Intel wireless MMX general purpose registers 0 - 7
  // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7)
  case dwarf_wCGR0:
    return "wCGR0/ACC0";
  case dwarf_wCGR1:
    return "wCGR1/ACC1";
  case dwarf_wCGR2:
    return "wCGR2/ACC2";
  case dwarf_wCGR3:
    return "wCGR3/ACC3";
  case dwarf_wCGR4:
    return "wCGR4/ACC4";
  case dwarf_wCGR5:
    return "wCGR5/ACC5";
  case dwarf_wCGR6:
    return "wCGR6/ACC6";
  case dwarf_wCGR7:
    return "wCGR7/ACC7";

  // Intel wireless MMX data registers 0 - 15
  case dwarf_wR0:
    return "wR0";
  case dwarf_wR1:
    return "wR1";
  case dwarf_wR2:
    return "wR2";
  case dwarf_wR3:
    return "wR3";
  case dwarf_wR4:
    return "wR4";
  case dwarf_wR5:
    return "wR5";
  case dwarf_wR6:
    return "wR6";
  case dwarf_wR7:
    return "wR7";
  case dwarf_wR8:
    return "wR8";
  case dwarf_wR9:
    return "wR9";
  case dwarf_wR10:
    return "wR10";
  case dwarf_wR11:
    return "wR11";
  case dwarf_wR12:
    return "wR12";
  case dwarf_wR13:
    return "wR13";
  case dwarf_wR14:
    return "wR14";
  case dwarf_wR15:
    return "wR15";

  case dwarf_spsr:
    return "spsr";
  case dwarf_spsr_fiq:
    return "spsr_fiq";
  case dwarf_spsr_irq:
    return "spsr_irq";
  case dwarf_spsr_abt:
    return "spsr_abt";
  case dwarf_spsr_und:
    return "spsr_und";
  case dwarf_spsr_svc:
    return "spsr_svc";

  case dwarf_r8_usr:
    return "r8_usr";
  case dwarf_r9_usr:
    return "r9_usr";
  case dwarf_r10_usr:
    return "r10_usr";
  case dwarf_r11_usr:
    return "r11_usr";
  case dwarf_r12_usr:
    return "r12_usr";
  case dwarf_r13_usr:
    return "r13_usr";
  case dwarf_r14_usr:
    return "r14_usr";
  case dwarf_r8_fiq:
    return "r8_fiq";
  case dwarf_r9_fiq:
    return "r9_fiq";
  case dwarf_r10_fiq:
    return "r10_fiq";
  case dwarf_r11_fiq:
    return "r11_fiq";
  case dwarf_r12_fiq:
    return "r12_fiq";
  case dwarf_r13_fiq:
    return "r13_fiq";
  case dwarf_r14_fiq:
    return "r14_fiq";
  case dwarf_r13_irq:
    return "r13_irq";
  case dwarf_r14_irq:
    return "r14_irq";
  case dwarf_r13_abt:
    return "r13_abt";
  case dwarf_r14_abt:
    return "r14_abt";
  case dwarf_r13_und:
    return "r13_und";
  case dwarf_r14_und:
    return "r14_und";
  case dwarf_r13_svc:
    return "r13_svc";
  case dwarf_r14_svc:
    return "r14_svc";

  // Intel wireless MMX control register in co-processor 0 - 7
  case dwarf_wC0:
    return "wC0";
  case dwarf_wC1:
    return "wC1";
  case dwarf_wC2:
    return "wC2";
  case dwarf_wC3:
    return "wC3";
  case dwarf_wC4:
    return "wC4";
  case dwarf_wC5:
    return "wC5";
  case dwarf_wC6:
    return "wC6";
  case dwarf_wC7:
    return "wC7";

  // VFP-v3/Neon
  case dwarf_d0:
    return "d0";
  case dwarf_d1:
    return "d1";
  case dwarf_d2:
    return "d2";
  case dwarf_d3:
    return "d3";
  case dwarf_d4:
    return "d4";
  case dwarf_d5:
    return "d5";
  case dwarf_d6:
    return "d6";
  case dwarf_d7:
    return "d7";
  case dwarf_d8:
    return "d8";
  case dwarf_d9:
    return "d9";
  case dwarf_d10:
    return "d10";
  case dwarf_d11:
    return "d11";
  case dwarf_d12:
    return "d12";
  case dwarf_d13:
    return "d13";
  case dwarf_d14:
    return "d14";
  case dwarf_d15:
    return "d15";
  case dwarf_d16:
    return "d16";
  case dwarf_d17:
    return "d17";
  case dwarf_d18:
    return "d18";
  case dwarf_d19:
    return "d19";
  case dwarf_d20:
    return "d20";
  case dwarf_d21:
    return "d21";
  case dwarf_d22:
    return "d22";
  case dwarf_d23:
    return "d23";
  case dwarf_d24:
    return "d24";
  case dwarf_d25:
    return "d25";
  case dwarf_d26:
    return "d26";
  case dwarf_d27:
    return "d27";
  case dwarf_d28:
    return "d28";
  case dwarf_d29:
    return "d29";
  case dwarf_d30:
    return "d30";
  case dwarf_d31:
    return "d31";

  // NEON 128-bit vector registers (overlays the d registers)
  case dwarf_q0:
    return "q0";
  case dwarf_q1:
    return "q1";
  case dwarf_q2:
    return "q2";
  case dwarf_q3:
    return "q3";
  case dwarf_q4:
    return "q4";
  case dwarf_q5:
    return "q5";
  case dwarf_q6:
    return "q6";
  case dwarf_q7:
    return "q7";
  case dwarf_q8:
    return "q8";
  case dwarf_q9:
    return "q9";
  case dwarf_q10:
    return "q10";
  case dwarf_q11:
    return "q11";
  case dwarf_q12:
    return "q12";
  case dwarf_q13:
    return "q13";
  case dwarf_q14:
    return "q14";
  case dwarf_q15:
    return "q15";
  }
  return nullptr;
}

bool GetARMDWARFRegisterInfo(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 >= dwarf_q0 && reg_num <= dwarf_q15) {
    reg_info.byte_size = 16;
    reg_info.format = eFormatVectorOfUInt8;
    reg_info.encoding = eEncodingVector;
  }

  if (reg_num >= dwarf_d0 && reg_num <= dwarf_d31) {
    reg_info.byte_size = 8;
    reg_info.format = eFormatFloat;
    reg_info.encoding = eEncodingIEEE754;
  } else if (reg_num >= dwarf_s0 && reg_num <= dwarf_s31) {
    reg_info.byte_size = 4;
    reg_info.format = eFormatFloat;
    reg_info.encoding = eEncodingIEEE754;
  } else if (reg_num >= dwarf_f0 && reg_num <= dwarf_f7) {
    reg_info.byte_size = 12;
    reg_info.format = eFormatFloat;
    reg_info.encoding = eEncodingIEEE754;
  } else {
    reg_info.byte_size = 4;
    reg_info.format = eFormatHex;
    reg_info.encoding = eEncodingUint;
  }

  reg_info.kinds[eRegisterKindDWARF] = reg_num;

  switch (reg_num) {
  case dwarf_r0:
    reg_info.name = "r0";
    break;
  case dwarf_r1:
    reg_info.name = "r1";
    break;
  case dwarf_r2:
    reg_info.name = "r2";
    break;
  case dwarf_r3:
    reg_info.name = "r3";
    break;
  case dwarf_r4:
    reg_info.name = "r4";
    break;
  case dwarf_r5:
    reg_info.name = "r5";
    break;
  case dwarf_r6:
    reg_info.name = "r6";
    break;
  case dwarf_r7:
    reg_info.name = "r7";
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FP;
    break;
  case dwarf_r8:
    reg_info.name = "r8";
    break;
  case dwarf_r9:
    reg_info.name = "r9";
    break;
  case dwarf_r10:
    reg_info.name = "r10";
    break;
  case dwarf_r11:
    reg_info.name = "r11";
    break;
  case dwarf_r12:
    reg_info.name = "r12";
    break;
  case dwarf_sp:
    reg_info.name = "sp";
    reg_info.alt_name = "r13";
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_SP;
    break;
  case dwarf_lr:
    reg_info.name = "lr";
    reg_info.alt_name = "r14";
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_RA;
    break;
  case dwarf_pc:
    reg_info.name = "pc";
    reg_info.alt_name = "r15";
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_PC;
    break;
  case dwarf_cpsr:
    reg_info.name = "cpsr";
    reg_info.kinds[eRegisterKindGeneric] = LLDB_REGNUM_GENERIC_FLAGS;
    break;

  case dwarf_s0:
    reg_info.name = "s0";
    break;
  case dwarf_s1:
    reg_info.name = "s1";
    break;
  case dwarf_s2:
    reg_info.name = "s2";
    break;
  case dwarf_s3:
    reg_info.name = "s3";
    break;
  case dwarf_s4:
    reg_info.name = "s4";
    break;
  case dwarf_s5:
    reg_info.name = "s5";
    break;
  case dwarf_s6:
    reg_info.name = "s6";
    break;
  case dwarf_s7:
    reg_info.name = "s7";
    break;
  case dwarf_s8:
    reg_info.name = "s8";
    break;
  case dwarf_s9:
    reg_info.name = "s9";
    break;
  case dwarf_s10:
    reg_info.name = "s10";
    break;
  case dwarf_s11:
    reg_info.name = "s11";
    break;
  case dwarf_s12:
    reg_info.name = "s12";
    break;
  case dwarf_s13:
    reg_info.name = "s13";
    break;
  case dwarf_s14:
    reg_info.name = "s14";
    break;
  case dwarf_s15:
    reg_info.name = "s15";
    break;
  case dwarf_s16:
    reg_info.name = "s16";
    break;
  case dwarf_s17:
    reg_info.name = "s17";
    break;
  case dwarf_s18:
    reg_info.name = "s18";
    break;
  case dwarf_s19:
    reg_info.name = "s19";
    break;
  case dwarf_s20:
    reg_info.name = "s20";
    break;
  case dwarf_s21:
    reg_info.name = "s21";
    break;
  case dwarf_s22:
    reg_info.name = "s22";
    break;
  case dwarf_s23:
    reg_info.name = "s23";
    break;
  case dwarf_s24:
    reg_info.name = "s24";
    break;
  case dwarf_s25:
    reg_info.name = "s25";
    break;
  case dwarf_s26:
    reg_info.name = "s26";
    break;
  case dwarf_s27:
    reg_info.name = "s27";
    break;
  case dwarf_s28:
    reg_info.name = "s28";
    break;
  case dwarf_s29:
    reg_info.name = "s29";
    break;
  case dwarf_s30:
    reg_info.name = "s30";
    break;
  case dwarf_s31:
    reg_info.name = "s31";
    break;

  // FPA Registers 0-7
  case dwarf_f0:
    reg_info.name = "f0";
    break;
  case dwarf_f1:
    reg_info.name = "f1";
    break;
  case dwarf_f2:
    reg_info.name = "f2";
    break;
  case dwarf_f3:
    reg_info.name = "f3";
    break;
  case dwarf_f4:
    reg_info.name = "f4";
    break;
  case dwarf_f5:
    reg_info.name = "f5";
    break;
  case dwarf_f6:
    reg_info.name = "f6";
    break;
  case dwarf_f7:
    reg_info.name = "f7";
    break;

  // Intel wireless MMX general purpose registers 0 - 7
  // XScale accumulator register 0 - 7 (they do overlap with wCGR0 - wCGR7)
  case dwarf_wCGR0:
    reg_info.name = "wCGR0/ACC0";
    break;
  case dwarf_wCGR1:
    reg_info.name = "wCGR1/ACC1";
    break;
  case dwarf_wCGR2:
    reg_info.name = "wCGR2/ACC2";
    break;
  case dwarf_wCGR3:
    reg_info.name = "wCGR3/ACC3";
    break;
  case dwarf_wCGR4:
    reg_info.name = "wCGR4/ACC4";
    break;
  case dwarf_wCGR5:
    reg_info.name = "wCGR5/ACC5";
    break;
  case dwarf_wCGR6:
    reg_info.name = "wCGR6/ACC6";
    break;
  case dwarf_wCGR7:
    reg_info.name = "wCGR7/ACC7";
    break;

  // Intel wireless MMX data registers 0 - 15
  case dwarf_wR0:
    reg_info.name = "wR0";
    break;
  case dwarf_wR1:
    reg_info.name = "wR1";
    break;
  case dwarf_wR2:
    reg_info.name = "wR2";
    break;
  case dwarf_wR3:
    reg_info.name = "wR3";
    break;
  case dwarf_wR4:
    reg_info.name = "wR4";
    break;
  case dwarf_wR5:
    reg_info.name = "wR5";
    break;
  case dwarf_wR6:
    reg_info.name = "wR6";
    break;
  case dwarf_wR7:
    reg_info.name = "wR7";
    break;
  case dwarf_wR8:
    reg_info.name = "wR8";
    break;
  case dwarf_wR9:
    reg_info.name = "wR9";
    break;
  case dwarf_wR10:
    reg_info.name = "wR10";
    break;
  case dwarf_wR11:
    reg_info.name = "wR11";
    break;
  case dwarf_wR12:
    reg_info.name = "wR12";
    break;
  case dwarf_wR13:
    reg_info.name = "wR13";
    break;
  case dwarf_wR14:
    reg_info.name = "wR14";
    break;
  case dwarf_wR15:
    reg_info.name = "wR15";
    break;

  case dwarf_spsr:
    reg_info.name = "spsr";
    break;
  case dwarf_spsr_fiq:
    reg_info.name = "spsr_fiq";
    break;
  case dwarf_spsr_irq:
    reg_info.name = "spsr_irq";
    break;
  case dwarf_spsr_abt:
    reg_info.name = "spsr_abt";
    break;
  case dwarf_spsr_und:
    reg_info.name = "spsr_und";
    break;
  case dwarf_spsr_svc:
    reg_info.name = "spsr_svc";
    break;

  case dwarf_r8_usr:
    reg_info.name = "r8_usr";
    break;
  case dwarf_r9_usr:
    reg_info.name = "r9_usr";
    break;
  case dwarf_r10_usr:
    reg_info.name = "r10_usr";
    break;
  case dwarf_r11_usr:
    reg_info.name = "r11_usr";
    break;
  case dwarf_r12_usr:
    reg_info.name = "r12_usr";
    break;
  case dwarf_r13_usr:
    reg_info.name = "r13_usr";
    break;
  case dwarf_r14_usr:
    reg_info.name = "r14_usr";
    break;
  case dwarf_r8_fiq:
    reg_info.name = "r8_fiq";
    break;
  case dwarf_r9_fiq:
    reg_info.name = "r9_fiq";
    break;
  case dwarf_r10_fiq:
    reg_info.name = "r10_fiq";
    break;
  case dwarf_r11_fiq:
    reg_info.name = "r11_fiq";
    break;
  case dwarf_r12_fiq:
    reg_info.name = "r12_fiq";
    break;
  case dwarf_r13_fiq:
    reg_info.name = "r13_fiq";
    break;
  case dwarf_r14_fiq:
    reg_info.name = "r14_fiq";
    break;
  case dwarf_r13_irq:
    reg_info.name = "r13_irq";
    break;
  case dwarf_r14_irq:
    reg_info.name = "r14_irq";
    break;
  case dwarf_r13_abt:
    reg_info.name = "r13_abt";
    break;
  case dwarf_r14_abt:
    reg_info.name = "r14_abt";
    break;
  case dwarf_r13_und:
    reg_info.name = "r13_und";
    break;
  case dwarf_r14_und:
    reg_info.name = "r14_und";
    break;
  case dwarf_r13_svc:
    reg_info.name = "r13_svc";
    break;
  case dwarf_r14_svc:
    reg_info.name = "r14_svc";
    break;

  // Intel wireless MMX control register in co-processor 0 - 7
  case dwarf_wC0:
    reg_info.name = "wC0";
    break;
  case dwarf_wC1:
    reg_info.name = "wC1";
    break;
  case dwarf_wC2:
    reg_info.name = "wC2";
    break;
  case dwarf_wC3:
    reg_info.name = "wC3";
    break;
  case dwarf_wC4:
    reg_info.name = "wC4";
    break;
  case dwarf_wC5:
    reg_info.name = "wC5";
    break;
  case dwarf_wC6:
    reg_info.name = "wC6";
    break;
  case dwarf_wC7:
    reg_info.name = "wC7";
    break;

  // VFP-v3/Neon
  case dwarf_d0:
    reg_info.name = "d0";
    break;
  case dwarf_d1:
    reg_info.name = "d1";
    break;
  case dwarf_d2:
    reg_info.name = "d2";
    break;
  case dwarf_d3:
    reg_info.name = "d3";
    break;
  case dwarf_d4:
    reg_info.name = "d4";
    break;
  case dwarf_d5:
    reg_info.name = "d5";
    break;
  case dwarf_d6:
    reg_info.name = "d6";
    break;
  case dwarf_d7:
    reg_info.name = "d7";
    break;
  case dwarf_d8:
    reg_info.name = "d8";
    break;
  case dwarf_d9:
    reg_info.name = "d9";
    break;
  case dwarf_d10:
    reg_info.name = "d10";
    break;
  case dwarf_d11:
    reg_info.name = "d11";
    break;
  case dwarf_d12:
    reg_info.name = "d12";
    break;
  case dwarf_d13:
    reg_info.name = "d13";
    break;
  case dwarf_d14:
    reg_info.name = "d14";
    break;
  case dwarf_d15:
    reg_info.name = "d15";
    break;
  case dwarf_d16:
    reg_info.name = "d16";
    break;
  case dwarf_d17:
    reg_info.name = "d17";
    break;
  case dwarf_d18:
    reg_info.name = "d18";
    break;
  case dwarf_d19:
    reg_info.name = "d19";
    break;
  case dwarf_d20:
    reg_info.name = "d20";
    break;
  case dwarf_d21:
    reg_info.name = "d21";
    break;
  case dwarf_d22:
    reg_info.name = "d22";
    break;
  case dwarf_d23:
    reg_info.name = "d23";
    break;
  case dwarf_d24:
    reg_info.name = "d24";
    break;
  case dwarf_d25:
    reg_info.name = "d25";
    break;
  case dwarf_d26:
    reg_info.name = "d26";
    break;
  case dwarf_d27:
    reg_info.name = "d27";
    break;
  case dwarf_d28:
    reg_info.name = "d28";
    break;
  case dwarf_d29:
    reg_info.name = "d29";
    break;
  case dwarf_d30:
    reg_info.name = "d30";
    break;
  case dwarf_d31:
    reg_info.name = "d31";
    break;

  // NEON 128-bit vector registers (overlays the d registers)
  case dwarf_q0:
    reg_info.name = "q0";
    break;
  case dwarf_q1:
    reg_info.name = "q1";
    break;
  case dwarf_q2:
    reg_info.name = "q2";
    break;
  case dwarf_q3:
    reg_info.name = "q3";
    break;
  case dwarf_q4:
    reg_info.name = "q4";
    break;
  case dwarf_q5:
    reg_info.name = "q5";
    break;
  case dwarf_q6:
    reg_info.name = "q6";
    break;
  case dwarf_q7:
    reg_info.name = "q7";
    break;
  case dwarf_q8:
    reg_info.name = "q8";
    break;
  case dwarf_q9:
    reg_info.name = "q9";
    break;
  case dwarf_q10:
    reg_info.name = "q10";
    break;
  case dwarf_q11:
    reg_info.name = "q11";
    break;
  case dwarf_q12:
    reg_info.name = "q12";
    break;
  case dwarf_q13:
    reg_info.name = "q13";
    break;
  case dwarf_q14:
    reg_info.name = "q14";
    break;
  case dwarf_q15:
    reg_info.name = "q15";
    break;

  default:
    return false;
  }
  return true;
}
