| 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 | |