1 //===-- RegisterInfoPOSIX_arm.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===---------------------------------------------------------------------===//
8 
9 #include <cassert>
10 #include <cstddef>
11 #include <vector>
12 
13 #include "lldb/lldb-defines.h"
14 #include "llvm/Support/Compiler.h"
15 
16 #include "RegisterInfoPOSIX_arm.h"
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 
21 // Based on RegisterContextDarwin_arm.cpp
22 #define GPR_OFFSET(idx) ((idx)*4)
23 #define FPU_OFFSET(idx) ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR))
24 #define FPSCR_OFFSET                                                           \
25   (LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::FPU, fpscr) +                \
26    sizeof(RegisterInfoPOSIX_arm::GPR))
27 #define EXC_OFFSET(idx)                                                        \
28   ((idx)*4 + sizeof(RegisterInfoPOSIX_arm::GPR) +                              \
29    sizeof(RegisterInfoPOSIX_arm::FPU))
30 #define DBG_OFFSET(reg)                                                        \
31   ((LLVM_EXTENSION offsetof(RegisterInfoPOSIX_arm::DBG, reg) +                 \
32     sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) +  \
33     sizeof(RegisterInfoPOSIX_arm::EXC)))
34 
35 #define DEFINE_DBG(reg, i)                                                     \
36   #reg, NULL, sizeof(((RegisterInfoPOSIX_arm::DBG *) NULL)->reg[i]),           \
37                       DBG_OFFSET(reg[i]), eEncodingUint, eFormatHex,           \
38                                  {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
39                                   LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    \
40                                   dbg_##reg##i },                              \
41                                   NULL, NULL, NULL,
42 #define REG_CONTEXT_SIZE                                                       \
43   (sizeof(RegisterInfoPOSIX_arm::GPR) + sizeof(RegisterInfoPOSIX_arm::FPU) +   \
44    sizeof(RegisterInfoPOSIX_arm::EXC))
45 
46 // Include RegisterInfos_arm to declare our g_register_infos_arm structure.
47 #define DECLARE_REGISTER_INFOS_ARM_STRUCT
48 #include "RegisterInfos_arm.h"
49 #undef DECLARE_REGISTER_INFOS_ARM_STRUCT
50 
51 static const lldb_private::RegisterInfo *
52 GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
53   switch (target_arch.GetMachine()) {
54   case llvm::Triple::arm:
55     return g_register_infos_arm;
56   default:
57     assert(false && "Unhandled target architecture.");
58     return nullptr;
59   }
60 }
61 
62 static uint32_t
63 GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch) {
64   switch (target_arch.GetMachine()) {
65   case llvm::Triple::arm:
66     return static_cast<uint32_t>(sizeof(g_register_infos_arm) /
67                                  sizeof(g_register_infos_arm[0]));
68   default:
69     assert(false && "Unhandled target architecture.");
70     return 0;
71   }
72 }
73 
74 // Number of register sets provided by this context.
75 enum {
76   k_num_gpr_registers = gpr_cpsr - gpr_r0 + 1,
77   k_num_fpr_registers = fpu_q15 - fpu_s0 + 1,
78   k_num_register_sets = 2
79 };
80 
81 // arm general purpose registers.
82 static const uint32_t g_gpr_regnums_arm[] = {
83     gpr_r0,   gpr_r1,
84     gpr_r2,   gpr_r3,
85     gpr_r4,   gpr_r5,
86     gpr_r6,   gpr_r7,
87     gpr_r8,   gpr_r9,
88     gpr_r10,  gpr_r11,
89     gpr_r12,  gpr_sp,
90     gpr_lr,   gpr_pc,
91     gpr_cpsr, LLDB_INVALID_REGNUM // register sets need to end with this flag
92 };
93 static_assert(((sizeof g_gpr_regnums_arm / sizeof g_gpr_regnums_arm[0]) - 1) ==
94                   k_num_gpr_registers,
95               "g_gpr_regnums_arm has wrong number of register infos");
96 
97 // arm floating point registers.
98 static const uint32_t g_fpu_regnums_arm[] = {
99     fpu_s0,    fpu_s1,
100     fpu_s2,    fpu_s3,
101     fpu_s4,    fpu_s5,
102     fpu_s6,    fpu_s7,
103     fpu_s8,    fpu_s9,
104     fpu_s10,   fpu_s11,
105     fpu_s12,   fpu_s13,
106     fpu_s14,   fpu_s15,
107     fpu_s16,   fpu_s17,
108     fpu_s18,   fpu_s19,
109     fpu_s20,   fpu_s21,
110     fpu_s22,   fpu_s23,
111     fpu_s24,   fpu_s25,
112     fpu_s26,   fpu_s27,
113     fpu_s28,   fpu_s29,
114     fpu_s30,   fpu_s31,
115     fpu_fpscr, fpu_d0,
116     fpu_d1,    fpu_d2,
117     fpu_d3,    fpu_d4,
118     fpu_d5,    fpu_d6,
119     fpu_d7,    fpu_d8,
120     fpu_d9,    fpu_d10,
121     fpu_d11,   fpu_d12,
122     fpu_d13,   fpu_d14,
123     fpu_d15,   fpu_d16,
124     fpu_d17,   fpu_d18,
125     fpu_d19,   fpu_d20,
126     fpu_d21,   fpu_d22,
127     fpu_d23,   fpu_d24,
128     fpu_d25,   fpu_d26,
129     fpu_d27,   fpu_d28,
130     fpu_d29,   fpu_d30,
131     fpu_d31,   fpu_q0,
132     fpu_q1,    fpu_q2,
133     fpu_q3,    fpu_q4,
134     fpu_q5,    fpu_q6,
135     fpu_q7,    fpu_q8,
136     fpu_q9,    fpu_q10,
137     fpu_q11,   fpu_q12,
138     fpu_q13,   fpu_q14,
139     fpu_q15,   LLDB_INVALID_REGNUM // register sets need to end with this flag
140 };
141 static_assert(((sizeof g_fpu_regnums_arm / sizeof g_fpu_regnums_arm[0]) - 1) ==
142                   k_num_fpr_registers,
143               "g_fpu_regnums_arm has wrong number of register infos");
144 
145 // Register sets for arm.
146 static const RegisterSet g_reg_sets_arm[k_num_register_sets] = {
147     {"General Purpose Registers", "gpr", k_num_gpr_registers,
148      g_gpr_regnums_arm},
149     {"Floating Point Registers", "fpu", k_num_fpr_registers,
150      g_fpu_regnums_arm}};
151 
152 RegisterInfoPOSIX_arm::RegisterInfoPOSIX_arm(
153     const lldb_private::ArchSpec &target_arch)
154     : lldb_private::RegisterInfoAndSetInterface(target_arch),
155       m_register_info_p(GetRegisterInfoPtr(target_arch)),
156       m_register_info_count(GetRegisterInfoCount(target_arch)) {}
157 
158 size_t RegisterInfoPOSIX_arm::GetGPRSize() const {
159   return sizeof(struct RegisterInfoPOSIX_arm::GPR);
160 }
161 
162 size_t RegisterInfoPOSIX_arm::GetFPRSize() const {
163   return sizeof(struct RegisterInfoPOSIX_arm::FPU);
164 }
165 
166 const lldb_private::RegisterInfo *
167 RegisterInfoPOSIX_arm::GetRegisterInfo() const {
168   return m_register_info_p;
169 }
170 
171 size_t RegisterInfoPOSIX_arm::GetRegisterSetCount() const {
172   return k_num_register_sets;
173 }
174 
175 size_t RegisterInfoPOSIX_arm::GetRegisterSetFromRegisterIndex(
176     uint32_t reg_index) const {
177   if (reg_index <= gpr_cpsr)
178     return GPRegSet;
179   if (reg_index <= fpu_q15)
180     return FPRegSet;
181   return LLDB_INVALID_REGNUM;
182 }
183 
184 const lldb_private::RegisterSet *
185 RegisterInfoPOSIX_arm::GetRegisterSet(size_t set_index) const {
186   if (set_index < GetRegisterSetCount())
187     return &g_reg_sets_arm[set_index];
188   return nullptr;
189 }
190 
191 uint32_t RegisterInfoPOSIX_arm::GetRegisterCount() const {
192   return m_register_info_count;
193 }
194