1 //===-- ABIX86.cpp --------------------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "ABIMacOSX_i386.h"
10 #include "ABISysV_i386.h"
11 #include "ABISysV_x86_64.h"
12 #include "ABIWindows_x86_64.h"
14 #include "lldb/Core/PluginManager.h"
15 #include "lldb/Target/Process.h"
19 using namespace lldb_private
;
21 LLDB_PLUGIN_DEFINE(ABIX86
)
23 void ABIX86::Initialize() {
24 ABIMacOSX_i386::Initialize();
25 ABISysV_i386::Initialize();
26 ABISysV_x86_64::Initialize();
27 ABIWindows_x86_64::Initialize();
30 void ABIX86::Terminate() {
31 ABIMacOSX_i386::Terminate();
32 ABISysV_i386::Terminate();
33 ABISysV_x86_64::Terminate();
34 ABIWindows_x86_64::Terminate();
53 llvm::StringRef subreg_name
;
54 std::optional
<uint32_t> base_index
;
58 addPartialRegisters(std::vector
<DynamicRegisterInfo::Register
> ®s
,
59 llvm::ArrayRef
<RegData
*> subregs
, uint32_t base_size
,
60 lldb::Encoding encoding
, lldb::Format format
,
61 uint32_t subreg_size
, uint32_t subreg_offset
= 0) {
62 for (const RegData
*subreg
: subregs
) {
64 uint32_t base_index
= *subreg
->base_index
;
65 DynamicRegisterInfo::Register
&full_reg
= regs
[base_index
];
66 if (full_reg
.byte_size
!= base_size
)
69 lldb_private::DynamicRegisterInfo::Register new_reg
{
70 lldb_private::ConstString(subreg
->subreg_name
),
71 lldb_private::ConstString(),
72 lldb_private::ConstString("supplementary registers"),
85 addSupplementaryRegister(regs
, new_reg
);
90 addCombinedRegisters(std::vector
<DynamicRegisterInfo::Register
> ®s
,
91 llvm::ArrayRef
<RegData
*> subregs1
,
92 llvm::ArrayRef
<RegData
*> subregs2
, uint32_t base_size
,
93 lldb::Encoding encoding
, lldb::Format format
) {
94 for (auto it
: llvm::zip(subregs1
, subregs2
)) {
95 RegData
*regdata1
, *regdata2
;
96 std::tie(regdata1
, regdata2
) = it
;
100 // verify that we've got matching target registers
101 if (regdata1
->subreg_name
!= regdata2
->subreg_name
)
104 uint32_t base_index1
= *regdata1
->base_index
;
105 uint32_t base_index2
= *regdata2
->base_index
;
106 if (regs
[base_index1
].byte_size
!= base_size
||
107 regs
[base_index2
].byte_size
!= base_size
)
110 lldb_private::DynamicRegisterInfo::Register new_reg
{
111 lldb_private::ConstString(regdata1
->subreg_name
),
112 lldb_private::ConstString(),
113 lldb_private::ConstString("supplementary registers"),
115 LLDB_INVALID_INDEX32
,
122 {base_index1
, base_index2
},
125 addSupplementaryRegister(regs
, new_reg
);
129 typedef llvm::SmallDenseMap
<llvm::StringRef
, llvm::SmallVector
<RegData
, 4>, 64>
134 is64bit ? BaseRegToRegsMap::value_type("r" l "x", \
135 {{GPR32, "e" l "x", std::nullopt}, \
136 {GPR16, l "x", std::nullopt}, \
137 {GPR8h, l "h", std::nullopt}, \
138 {GPR8, l "l", std::nullopt}}) \
139 : BaseRegToRegsMap::value_type("e" l "x", \
140 {{GPR16, l "x", std::nullopt}, \
141 {GPR8h, l "h", std::nullopt}, \
142 {GPR8, l "l", std::nullopt}}) \
147 is64bit ? BaseRegToRegsMap::value_type("r" r16, \
148 {{GPR32, "e" r16, std::nullopt}, \
149 {GPR16, r16, std::nullopt}, \
150 {GPR8, r16 "l", std::nullopt}}) \
151 : BaseRegToRegsMap::value_type( \
153 {{GPR16, r16, std::nullopt}, {GPR8, r16 "l", std::nullopt}}) \
158 BaseRegToRegsMap::value_type("r" #n, {{GPR32, "r" #n "d", std::nullopt}, \
159 {GPR16, "r" #n "w", std::nullopt}, \
160 {GPR8, "r" #n "l", std::nullopt}}) \
164 { BaseRegToRegsMap::value_type("st" #n, {{MM, "mm" #n, std::nullopt}}) }
167 {BaseRegToRegsMap::value_type("ymm" #n "h", \
168 {{YMM_YMMh, "ymm" #n, std::nullopt}})}, \
170 BaseRegToRegsMap::value_type("xmm" #n, \
171 {{YMM_XMM, "ymm" #n, std::nullopt}}) \
174 BaseRegToRegsMap
makeBaseRegMap(bool is64bit
) {
175 BaseRegToRegsMap out
{
176 {// GPRs common to amd64 & i386
177 GPRh("a"), GPRh("b"), GPRh("c"), GPRh("d"), GPR("si"), GPR("di"),
178 GPR("bp"), GPR("sp"),
181 STMM(0), STMM(1), STMM(2), STMM(3), STMM(4), STMM(5), STMM(6), STMM(7),
183 // lower YMM registers (common to amd64 & i386)
184 YMM(0), YMM(1), YMM(2), YMM(3), YMM(4), YMM(5), YMM(6), YMM(7)}};
187 BaseRegToRegsMap amd64_regs
{{// GPRs specific to amd64
188 GPR64(8), GPR64(9), GPR64(10), GPR64(11),
189 GPR64(12), GPR64(13), GPR64(14), GPR64(15),
191 // higher YMM registers (specific to amd64)
192 YMM(8), YMM(9), YMM(10), YMM(11), YMM(12),
193 YMM(13), YMM(14), YMM(15)}};
194 out
.insert(amd64_regs
.begin(), amd64_regs
.end());
200 void ABIX86::AugmentRegisterInfo(
201 std::vector
<DynamicRegisterInfo::Register
> ®s
) {
202 MCBasedABI::AugmentRegisterInfo(regs
);
204 ProcessSP process_sp
= GetProcessSP();
208 uint32_t gpr_base_size
=
209 process_sp
->GetTarget().GetArchitecture().GetAddressByteSize();
211 // primary map from a base register to its subregisters
212 BaseRegToRegsMap base_reg_map
= makeBaseRegMap(gpr_base_size
== 8);
213 // set used for fast matching of register names to subregisters
214 llvm::SmallDenseSet
<llvm::StringRef
, 64> subreg_name_set
;
215 // convenience array providing access to all subregisters of given kind,
216 // sorted by base register index
217 std::array
<llvm::SmallVector
<RegData
*, 16>, RegKindCount
> subreg_by_kind
;
219 // prepare the set of all known subregisters
220 for (const auto &x
: base_reg_map
) {
221 for (const auto &subreg
: x
.second
)
222 subreg_name_set
.insert(subreg
.subreg_name
);
225 // iterate over all registers
226 for (const auto &x
: llvm::enumerate(regs
)) {
227 llvm::StringRef reg_name
= x
.value().name
.GetStringRef();
228 // abort if at least one sub-register is already present
229 if (llvm::is_contained(subreg_name_set
, reg_name
))
232 auto found
= base_reg_map
.find(reg_name
);
233 if (found
== base_reg_map
.end())
236 for (auto &subreg
: found
->second
) {
237 // fill in base register indices
238 subreg
.base_index
= x
.index();
239 // fill subreg_by_kind map-array
240 subreg_by_kind
[static_cast<size_t>(subreg
.subreg_kind
)].push_back(
245 // now add registers by kind
246 addPartialRegisters(regs
, subreg_by_kind
[GPR32
], gpr_base_size
, eEncodingUint
,
248 addPartialRegisters(regs
, subreg_by_kind
[GPR16
], gpr_base_size
, eEncodingUint
,
250 addPartialRegisters(regs
, subreg_by_kind
[GPR8h
], gpr_base_size
, eEncodingUint
,
252 addPartialRegisters(regs
, subreg_by_kind
[GPR8
], gpr_base_size
, eEncodingUint
,
255 addPartialRegisters(regs
, subreg_by_kind
[MM
], 10, eEncodingUint
, eFormatHex
,
258 addCombinedRegisters(regs
, subreg_by_kind
[YMM_XMM
], subreg_by_kind
[YMM_YMMh
],
259 16, eEncodingVector
, eFormatVectorOfUInt8
);