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 | {.name: "General Purpose Registers" , .short_name: "gpr" , .num_registers: k_num_gpr_registers, |
148 | .registers: g_gpr_regnums_arm}, |
149 | {.name: "Floating Point Registers" , .short_name: "fpu" , .num_registers: k_num_fpr_registers, |
150 | .registers: 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 | |