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
18using namespace lldb;
19using 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
51static const lldb_private::RegisterInfo *
52GetRegisterInfoPtr(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
62static uint32_t
63GetRegisterInfoCount(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.
75enum {
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.
82static 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};
93static_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.
98static 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};
141static_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.
146static 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
152RegisterInfoPOSIX_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
158size_t RegisterInfoPOSIX_arm::GetGPRSize() const {
159 return sizeof(struct RegisterInfoPOSIX_arm::GPR);
160}
161
162size_t RegisterInfoPOSIX_arm::GetFPRSize() const {
163 return sizeof(struct RegisterInfoPOSIX_arm::FPU);
164}
165
166const lldb_private::RegisterInfo *
167RegisterInfoPOSIX_arm::GetRegisterInfo() const {
168 return m_register_info_p;
169}
170
171size_t RegisterInfoPOSIX_arm::GetRegisterSetCount() const {
172 return k_num_register_sets;
173}
174
175size_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
184const lldb_private::RegisterSet *
185RegisterInfoPOSIX_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
191uint32_t RegisterInfoPOSIX_arm::GetRegisterCount() const {
192 return m_register_info_count;
193}
194

source code of lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm.cpp