1dda28197Spatrick //===-- RegisterInfoPOSIX_arm.cpp -----------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===---------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include <cassert>
10be691f3bSpatrick #include <cstddef>
11061da546Spatrick #include <vector>
12061da546Spatrick 
13061da546Spatrick #include "lldb/lldb-defines.h"
14061da546Spatrick #include "llvm/Support/Compiler.h"
15061da546Spatrick 
16061da546Spatrick #include "RegisterInfoPOSIX_arm.h"
17061da546Spatrick 
18061da546Spatrick using namespace lldb;
19061da546Spatrick using namespace lldb_private;
20061da546Spatrick 
21061da546Spatrick // Based on RegisterContextDarwin_arm.cpp
22061da546Spatrick #define GPR_OFFSET(idx) ((idx)*4)
23061da546Spatrick #define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR))
24061da546Spatrick #define FPSCR_OFFSET                                                           \
25061da546Spatrick   (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::FPU, fpscr) +                \
26061da546Spatrick    sizeof(RegisterInfoPOSIX_arm::GPR))
27061da546Spatrick #define EXC_OFFSET(idx)                                                        \
28061da546Spatrick   ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR) +                              \
29061da546Spatrick    sizeof(RegisterInfoPOSIX_arm::FPU))
30061da546Spatrick #define DBG_OFFSET(reg)                                                        \
31061da546Spatrick   ((LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::DBG, reg) +                 \
32061da546Spatrick     sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) +  \
33061da546Spatrick     sizeof(RegisterInfoPOSIX_arm::EXC)))
34061da546Spatrick 
35061da546Spatrick #define DEFINE_DBG(reg, i)                                                     \
36061da546Spatrick   #reg, NULL, sizeof(((RegisterInfoPOSIX_arm::DBG *) NULL)->reg[i]),           \
37061da546Spatrick                       DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex,           \
38061da546Spatrick                                  {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
39061da546Spatrick                                   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
40061da546Spatrick                                   dbg_##reg##i },                              \
41*f6aab3d8Srobert                                   NULL, NULL,
42061da546Spatrick #define REG_CONTEXT_SIZE                                                       \
43061da546Spatrick   (sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) +   \
44061da546Spatrick    sizeof(RegisterInfoPOSIX_arm::EXC))
45061da546Spatrick 
46061da546Spatrick // Include RegisterInfos_arm to declare our g_register_infos_arm structure.
47061da546Spatrick #define DECLARE_REGISTER_INFOS_ARM_STRUCT
48061da546Spatrick #include "RegisterInfos_arm.h"
49061da546Spatrick #undef DECLARE_REGISTER_INFOS_ARM_STRUCT
50061da546Spatrick 
51061da546Spatrick static const lldb_private::RegisterInfo *
GetRegisterInfoPtr(const lldb_private::ArchSpec & target_arch)52061da546Spatrick GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
53061da546Spatrick   switch (target_arch.GetMachine()) {
54061da546Spatrick   case llvm::Triple::arm:
55061da546Spatrick     return g_register_infos_arm;
56061da546Spatrick   default:
57061da546Spatrick     assert(false && "Unhandled target architecture.");
58061da546Spatrick     return nullptr;
59061da546Spatrick   }
60061da546Spatrick }
61061da546Spatrick 
62061da546Spatrick static uint32_t
GetRegisterInfoCount(const lldb_private::ArchSpec & target_arch)63061da546Spatrick GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
64061da546Spatrick   switch (target_arch.GetMachine()) {
65061da546Spatrick   case llvm::Triple::arm:
66061da546Spatrick     return static_cast<uint32_t>(sizeof(g_register_infos_arm) /
67061da546Spatrick                                  sizeof(g_register_infos_arm[0]));
68061da546Spatrick   default:
69061da546Spatrick     assert(false && "Unhandled target architecture.");
70061da546Spatrick     return 0;
71061da546Spatrick   }
72061da546Spatrick }
73061da546Spatrick 
74be691f3bSpatrick // Number of register sets provided by this context.
75be691f3bSpatrick enum {
76be691f3bSpatrick   k_num_gpr_registers = gpr_cpsr - gpr_r0 + 1,
77be691f3bSpatrick   k_num_fpr_registers = fpu_q15 - fpu_s0 + 1,
78be691f3bSpatrick   k_num_register_sets = 2
79be691f3bSpatrick };
80be691f3bSpatrick 
81be691f3bSpatrick // arm general purpose registers.
82be691f3bSpatrick static const uint32_t g_gpr_regnums_arm[] = {
83be691f3bSpatrick     gpr_r0,   gpr_r1,
84be691f3bSpatrick     gpr_r2,   gpr_r3,
85be691f3bSpatrick     gpr_r4,   gpr_r5,
86be691f3bSpatrick     gpr_r6,   gpr_r7,
87be691f3bSpatrick     gpr_r8,   gpr_r9,
88be691f3bSpatrick     gpr_r10,  gpr_r11,
89be691f3bSpatrick     gpr_r12,  gpr_sp,
90be691f3bSpatrick     gpr_lr,   gpr_pc,
91be691f3bSpatrick     gpr_cpsr, LLDB_INVALID_REGNUM // register sets need to end with this flag
92be691f3bSpatrick };
93be691f3bSpatrick static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) ==
94be691f3bSpatrick                   k_num_gpr_registers,
95be691f3bSpatrick               "g_gpr_regnums_arm has wrong number of register infos");
96be691f3bSpatrick 
97be691f3bSpatrick // arm floating point registers.
98be691f3bSpatrick static const uint32_t g_fpu_regnums_arm[] = {
99be691f3bSpatrick     fpu_s0,    fpu_s1,
100be691f3bSpatrick     fpu_s2,    fpu_s3,
101be691f3bSpatrick     fpu_s4,    fpu_s5,
102be691f3bSpatrick     fpu_s6,    fpu_s7,
103be691f3bSpatrick     fpu_s8,    fpu_s9,
104be691f3bSpatrick     fpu_s10,   fpu_s11,
105be691f3bSpatrick     fpu_s12,   fpu_s13,
106be691f3bSpatrick     fpu_s14,   fpu_s15,
107be691f3bSpatrick     fpu_s16,   fpu_s17,
108be691f3bSpatrick     fpu_s18,   fpu_s19,
109be691f3bSpatrick     fpu_s20,   fpu_s21,
110be691f3bSpatrick     fpu_s22,   fpu_s23,
111be691f3bSpatrick     fpu_s24,   fpu_s25,
112be691f3bSpatrick     fpu_s26,   fpu_s27,
113be691f3bSpatrick     fpu_s28,   fpu_s29,
114be691f3bSpatrick     fpu_s30,   fpu_s31,
115be691f3bSpatrick     fpu_fpscr, fpu_d0,
116be691f3bSpatrick     fpu_d1,    fpu_d2,
117be691f3bSpatrick     fpu_d3,    fpu_d4,
118be691f3bSpatrick     fpu_d5,    fpu_d6,
119be691f3bSpatrick     fpu_d7,    fpu_d8,
120be691f3bSpatrick     fpu_d9,    fpu_d10,
121be691f3bSpatrick     fpu_d11,   fpu_d12,
122be691f3bSpatrick     fpu_d13,   fpu_d14,
123be691f3bSpatrick     fpu_d15,   fpu_d16,
124be691f3bSpatrick     fpu_d17,   fpu_d18,
125be691f3bSpatrick     fpu_d19,   fpu_d20,
126be691f3bSpatrick     fpu_d21,   fpu_d22,
127be691f3bSpatrick     fpu_d23,   fpu_d24,
128be691f3bSpatrick     fpu_d25,   fpu_d26,
129be691f3bSpatrick     fpu_d27,   fpu_d28,
130be691f3bSpatrick     fpu_d29,   fpu_d30,
131be691f3bSpatrick     fpu_d31,   fpu_q0,
132be691f3bSpatrick     fpu_q1,    fpu_q2,
133be691f3bSpatrick     fpu_q3,    fpu_q4,
134be691f3bSpatrick     fpu_q5,    fpu_q6,
135be691f3bSpatrick     fpu_q7,    fpu_q8,
136be691f3bSpatrick     fpu_q9,    fpu_q10,
137be691f3bSpatrick     fpu_q11,   fpu_q12,
138be691f3bSpatrick     fpu_q13,   fpu_q14,
139be691f3bSpatrick     fpu_q15,   LLDB_INVALID_REGNUM // register sets need to end with this flag
140be691f3bSpatrick };
141be691f3bSpatrick static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) ==
142be691f3bSpatrick                   k_num_fpr_registers,
143be691f3bSpatrick               "g_fpu_regnums_arm has wrong number of register infos");
144be691f3bSpatrick 
145be691f3bSpatrick // Register sets for arm.
146be691f3bSpatrick static const RegisterSet g_reg_sets_arm[k_num_register_sets] = {
147be691f3bSpatrick     {"General Purpose Registers", "gpr", k_num_gpr_registers,
148be691f3bSpatrick      g_gpr_regnums_arm},
149be691f3bSpatrick     {"Floating Point Registers", "fpu", k_num_fpr_registers,
150be691f3bSpatrick      g_fpu_regnums_arm}};
151be691f3bSpatrick 
RegisterInfoPOSIX_arm(const lldb_private::ArchSpec & target_arch)152061da546Spatrick RegisterInfoPOSIX_arm::RegisterInfoPOSIX_arm(
153061da546Spatrick     const lldb_private::ArchSpec &target_arch)
154be691f3bSpatrick     : lldb_private::RegisterInfoAndSetInterface(target_arch),
155061da546Spatrick       m_register_info_p(GetRegisterInfoPtr(target_arch)),
156061da546Spatrick       m_register_info_count(GetRegisterInfoCount(target_arch)) {}
157061da546Spatrick 
GetGPRSize() const158061da546Spatrick size_t RegisterInfoPOSIX_arm::GetGPRSize() const {
159061da546Spatrick   return sizeof(struct RegisterInfoPOSIX_arm::GPR);
160061da546Spatrick }
161061da546Spatrick 
GetFPRSize() const162be691f3bSpatrick size_t RegisterInfoPOSIX_arm::GetFPRSize() const {
163be691f3bSpatrick   return sizeof(struct RegisterInfoPOSIX_arm::FPU);
164be691f3bSpatrick }
165be691f3bSpatrick 
166061da546Spatrick const lldb_private::RegisterInfo *
GetRegisterInfo() const167061da546Spatrick RegisterInfoPOSIX_arm::GetRegisterInfo() const {
168061da546Spatrick   return m_register_info_p;
169061da546Spatrick }
170061da546Spatrick 
GetRegisterSetCount() const171be691f3bSpatrick size_t RegisterInfoPOSIX_arm::GetRegisterSetCount() const {
172be691f3bSpatrick   return k_num_register_sets;
173be691f3bSpatrick }
174be691f3bSpatrick 
GetRegisterSetFromRegisterIndex(uint32_t reg_index) const175be691f3bSpatrick size_t RegisterInfoPOSIX_arm::GetRegisterSetFromRegisterIndex(
176be691f3bSpatrick     uint32_t reg_index) const {
177be691f3bSpatrick   if (reg_index <= gpr_cpsr)
178be691f3bSpatrick     return GPRegSet;
179be691f3bSpatrick   if (reg_index <= fpu_q15)
180be691f3bSpatrick     return FPRegSet;
181be691f3bSpatrick   return LLDB_INVALID_REGNUM;
182be691f3bSpatrick }
183be691f3bSpatrick 
184be691f3bSpatrick const lldb_private::RegisterSet *
GetRegisterSet(size_t set_index) const185be691f3bSpatrick RegisterInfoPOSIX_arm::GetRegisterSet(size_t set_index) const {
186be691f3bSpatrick   if (set_index < GetRegisterSetCount())
187be691f3bSpatrick     return &g_reg_sets_arm[set_index];
188be691f3bSpatrick   return nullptr;
189be691f3bSpatrick }
190be691f3bSpatrick 
GetRegisterCount() const191061da546Spatrick uint32_t RegisterInfoPOSIX_arm::GetRegisterCount() const {
192061da546Spatrick   return m_register_info_count;
193061da546Spatrick }
194