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