xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/ABI/X86/ABIX86.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
1349cc55cSDimitry Andric //===-- ABIX86.cpp --------------------------------------------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65ffd83dbSDimitry Andric //
75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
85ffd83dbSDimitry Andric 
9580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
105ffd83dbSDimitry Andric #include "ABIMacOSX_i386.h"
11580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
125ffd83dbSDimitry Andric #include "ABISysV_i386.h"
135ffd83dbSDimitry Andric #include "ABISysV_x86_64.h"
14580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
155ffd83dbSDimitry Andric #include "ABIWindows_x86_64.h"
16580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
17349cc55cSDimitry Andric #include "ABIX86.h"
185ffd83dbSDimitry Andric #include "lldb/Core/PluginManager.h"
19349cc55cSDimitry Andric #include "lldb/Target/Process.h"
20*bdd1243dSDimitry Andric #include <optional>
21349cc55cSDimitry Andric 
22349cc55cSDimitry Andric using namespace lldb;
23349cc55cSDimitry Andric using namespace lldb_private;
245ffd83dbSDimitry Andric 
LLDB_PLUGIN_DEFINE(ABIX86)255ffd83dbSDimitry Andric LLDB_PLUGIN_DEFINE(ABIX86)
265ffd83dbSDimitry Andric 
275ffd83dbSDimitry Andric void ABIX86::Initialize() {
28580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
295ffd83dbSDimitry Andric   ABIMacOSX_i386::Initialize();
30580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
315ffd83dbSDimitry Andric   ABISysV_i386::Initialize();
325ffd83dbSDimitry Andric   ABISysV_x86_64::Initialize();
33580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
345ffd83dbSDimitry Andric   ABIWindows_x86_64::Initialize();
35580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
365ffd83dbSDimitry Andric }
375ffd83dbSDimitry Andric 
Terminate()385ffd83dbSDimitry Andric void ABIX86::Terminate() {
39580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
405ffd83dbSDimitry Andric   ABIMacOSX_i386::Terminate();
41580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
425ffd83dbSDimitry Andric   ABISysV_i386::Terminate();
435ffd83dbSDimitry Andric   ABISysV_x86_64::Terminate();
44580012d6SDimitry Andric #ifdef LLDB_ENABLE_ALL
455ffd83dbSDimitry Andric   ABIWindows_x86_64::Terminate();
46580012d6SDimitry Andric #endif // LLDB_ENABLE_ALL
475ffd83dbSDimitry Andric }
485ffd83dbSDimitry Andric 
49349cc55cSDimitry Andric namespace {
50349cc55cSDimitry Andric enum RegKind {
51349cc55cSDimitry Andric   GPR32,
52349cc55cSDimitry Andric   GPR16,
53349cc55cSDimitry Andric   GPR8h,
54349cc55cSDimitry Andric   GPR8,
55349cc55cSDimitry Andric   MM,
56349cc55cSDimitry Andric   YMM_YMMh,
57349cc55cSDimitry Andric   YMM_XMM,
58349cc55cSDimitry Andric 
59349cc55cSDimitry Andric   RegKindCount
60349cc55cSDimitry Andric };
61349cc55cSDimitry Andric }
62349cc55cSDimitry Andric 
63349cc55cSDimitry Andric struct RegData {
64349cc55cSDimitry Andric   RegKind subreg_kind;
65349cc55cSDimitry Andric   llvm::StringRef subreg_name;
66*bdd1243dSDimitry Andric   std::optional<uint32_t> base_index;
67349cc55cSDimitry Andric };
68349cc55cSDimitry Andric 
69349cc55cSDimitry Andric static void
addPartialRegisters(std::vector<DynamicRegisterInfo::Register> & regs,llvm::ArrayRef<RegData * > subregs,uint32_t base_size,lldb::Encoding encoding,lldb::Format format,uint32_t subreg_size,uint32_t subreg_offset=0)70349cc55cSDimitry Andric addPartialRegisters(std::vector<DynamicRegisterInfo::Register> &regs,
71349cc55cSDimitry Andric                     llvm::ArrayRef<RegData *> subregs, uint32_t base_size,
72349cc55cSDimitry Andric                     lldb::Encoding encoding, lldb::Format format,
73349cc55cSDimitry Andric                     uint32_t subreg_size, uint32_t subreg_offset = 0) {
74349cc55cSDimitry Andric   for (const RegData *subreg : subregs) {
75349cc55cSDimitry Andric     assert(subreg);
7681ad6265SDimitry Andric     uint32_t base_index = *subreg->base_index;
77349cc55cSDimitry Andric     DynamicRegisterInfo::Register &full_reg = regs[base_index];
78349cc55cSDimitry Andric     if (full_reg.byte_size != base_size)
79349cc55cSDimitry Andric       continue;
80349cc55cSDimitry Andric 
81349cc55cSDimitry Andric     lldb_private::DynamicRegisterInfo::Register new_reg{
82349cc55cSDimitry Andric         lldb_private::ConstString(subreg->subreg_name),
83349cc55cSDimitry Andric         lldb_private::ConstString(),
84349cc55cSDimitry Andric         lldb_private::ConstString("supplementary registers"),
85349cc55cSDimitry Andric         subreg_size,
86349cc55cSDimitry Andric         LLDB_INVALID_INDEX32,
87349cc55cSDimitry Andric         encoding,
88349cc55cSDimitry Andric         format,
89349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
90349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
91349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
92349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
93349cc55cSDimitry Andric         {base_index},
94349cc55cSDimitry Andric         {},
95349cc55cSDimitry Andric         subreg_offset};
96349cc55cSDimitry Andric 
97349cc55cSDimitry Andric     addSupplementaryRegister(regs, new_reg);
98349cc55cSDimitry Andric   }
99349cc55cSDimitry Andric }
100349cc55cSDimitry Andric 
101349cc55cSDimitry Andric static void
addCombinedRegisters(std::vector<DynamicRegisterInfo::Register> & regs,llvm::ArrayRef<RegData * > subregs1,llvm::ArrayRef<RegData * > subregs2,uint32_t base_size,lldb::Encoding encoding,lldb::Format format)102349cc55cSDimitry Andric addCombinedRegisters(std::vector<DynamicRegisterInfo::Register> &regs,
103349cc55cSDimitry Andric                      llvm::ArrayRef<RegData *> subregs1,
104349cc55cSDimitry Andric                      llvm::ArrayRef<RegData *> subregs2, uint32_t base_size,
105349cc55cSDimitry Andric                      lldb::Encoding encoding, lldb::Format format) {
106349cc55cSDimitry Andric   for (auto it : llvm::zip(subregs1, subregs2)) {
107349cc55cSDimitry Andric     RegData *regdata1, *regdata2;
108349cc55cSDimitry Andric     std::tie(regdata1, regdata2) = it;
109349cc55cSDimitry Andric     assert(regdata1);
110349cc55cSDimitry Andric     assert(regdata2);
111349cc55cSDimitry Andric 
112349cc55cSDimitry Andric     // verify that we've got matching target registers
113349cc55cSDimitry Andric     if (regdata1->subreg_name != regdata2->subreg_name)
114349cc55cSDimitry Andric       continue;
115349cc55cSDimitry Andric 
116*bdd1243dSDimitry Andric     uint32_t base_index1 = *regdata1->base_index;
117*bdd1243dSDimitry Andric     uint32_t base_index2 = *regdata2->base_index;
118349cc55cSDimitry Andric     if (regs[base_index1].byte_size != base_size ||
119349cc55cSDimitry Andric         regs[base_index2].byte_size != base_size)
120349cc55cSDimitry Andric       continue;
121349cc55cSDimitry Andric 
122349cc55cSDimitry Andric     lldb_private::DynamicRegisterInfo::Register new_reg{
123349cc55cSDimitry Andric         lldb_private::ConstString(regdata1->subreg_name),
124349cc55cSDimitry Andric         lldb_private::ConstString(),
125349cc55cSDimitry Andric         lldb_private::ConstString("supplementary registers"),
126349cc55cSDimitry Andric         base_size * 2,
127349cc55cSDimitry Andric         LLDB_INVALID_INDEX32,
128349cc55cSDimitry Andric         encoding,
129349cc55cSDimitry Andric         format,
130349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
131349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
132349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
133349cc55cSDimitry Andric         LLDB_INVALID_REGNUM,
134349cc55cSDimitry Andric         {base_index1, base_index2},
135349cc55cSDimitry Andric         {}};
136349cc55cSDimitry Andric 
137349cc55cSDimitry Andric     addSupplementaryRegister(regs, new_reg);
138349cc55cSDimitry Andric   }
139349cc55cSDimitry Andric }
140349cc55cSDimitry Andric 
141349cc55cSDimitry Andric typedef llvm::SmallDenseMap<llvm::StringRef, llvm::SmallVector<RegData, 4>, 64>
142349cc55cSDimitry Andric     BaseRegToRegsMap;
143349cc55cSDimitry Andric 
144349cc55cSDimitry Andric #define GPRh(l)                                                                \
145349cc55cSDimitry Andric   {                                                                            \
146*bdd1243dSDimitry Andric     is64bit ? BaseRegToRegsMap::value_type("r" l "x",                          \
147*bdd1243dSDimitry Andric                                            {{GPR32, "e" l "x", std::nullopt},  \
148*bdd1243dSDimitry Andric                                             {GPR16, l "x", std::nullopt},      \
149*bdd1243dSDimitry Andric                                             {GPR8h, l "h", std::nullopt},      \
150*bdd1243dSDimitry Andric                                             {GPR8, l "l", std::nullopt}})      \
151*bdd1243dSDimitry Andric             : BaseRegToRegsMap::value_type("e" l "x",                          \
152*bdd1243dSDimitry Andric                                            {{GPR16, l "x", std::nullopt},      \
153*bdd1243dSDimitry Andric                                             {GPR8h, l "h", std::nullopt},      \
154*bdd1243dSDimitry Andric                                             {GPR8, l "l", std::nullopt}})      \
155349cc55cSDimitry Andric   }
156349cc55cSDimitry Andric 
157349cc55cSDimitry Andric #define GPR(r16)                                                               \
158349cc55cSDimitry Andric   {                                                                            \
159*bdd1243dSDimitry Andric     is64bit ? BaseRegToRegsMap::value_type("r" r16,                            \
160*bdd1243dSDimitry Andric                                            {{GPR32, "e" r16, std::nullopt},    \
161*bdd1243dSDimitry Andric                                             {GPR16, r16, std::nullopt},        \
162*bdd1243dSDimitry Andric                                             {GPR8, r16 "l", std::nullopt}})    \
163*bdd1243dSDimitry Andric             : BaseRegToRegsMap::value_type(                                    \
164*bdd1243dSDimitry Andric                   "e" r16,                                                     \
165*bdd1243dSDimitry Andric                   {{GPR16, r16, std::nullopt}, {GPR8, r16 "l", std::nullopt}}) \
166349cc55cSDimitry Andric   }
167349cc55cSDimitry Andric 
168349cc55cSDimitry Andric #define GPR64(n)                                                               \
169349cc55cSDimitry Andric   {                                                                            \
170*bdd1243dSDimitry Andric     BaseRegToRegsMap::value_type("r" #n, {{GPR32, "r" #n "d", std::nullopt},   \
171*bdd1243dSDimitry Andric                                           {GPR16, "r" #n "w", std::nullopt},   \
172*bdd1243dSDimitry Andric                                           {GPR8, "r" #n "l", std::nullopt}})   \
173349cc55cSDimitry Andric   }
174349cc55cSDimitry Andric 
175349cc55cSDimitry Andric #define STMM(n)                                                                \
176*bdd1243dSDimitry Andric   { BaseRegToRegsMap::value_type("st" #n, {{MM, "mm" #n, std::nullopt}}) }
177349cc55cSDimitry Andric 
178349cc55cSDimitry Andric #define YMM(n)                                                                 \
179349cc55cSDimitry Andric   {BaseRegToRegsMap::value_type("ymm" #n "h",                                  \
180*bdd1243dSDimitry Andric                                 {{YMM_YMMh, "ymm" #n, std::nullopt}})},        \
181349cc55cSDimitry Andric   {                                                                            \
182*bdd1243dSDimitry Andric     BaseRegToRegsMap::value_type("xmm" #n,                                     \
183*bdd1243dSDimitry Andric                                  {{YMM_XMM, "ymm" #n, std::nullopt}})          \
184349cc55cSDimitry Andric   }
185349cc55cSDimitry Andric 
makeBaseRegMap(bool is64bit)186349cc55cSDimitry Andric BaseRegToRegsMap makeBaseRegMap(bool is64bit) {
187349cc55cSDimitry Andric   BaseRegToRegsMap out{
188349cc55cSDimitry Andric       {// GPRs common to amd64 & i386
189349cc55cSDimitry Andric        GPRh("a"), GPRh("b"), GPRh("c"), GPRh("d"), GPR("si"), GPR("di"),
190349cc55cSDimitry Andric        GPR("bp"), GPR("sp"),
191349cc55cSDimitry Andric 
192349cc55cSDimitry Andric        // ST/MM registers
193349cc55cSDimitry Andric        STMM(0), STMM(1), STMM(2), STMM(3), STMM(4), STMM(5), STMM(6), STMM(7),
194349cc55cSDimitry Andric 
195349cc55cSDimitry Andric        // lower YMM registers (common to amd64 & i386)
196349cc55cSDimitry Andric        YMM(0), YMM(1), YMM(2), YMM(3), YMM(4), YMM(5), YMM(6), YMM(7)}};
197349cc55cSDimitry Andric 
198349cc55cSDimitry Andric   if (is64bit) {
199349cc55cSDimitry Andric     BaseRegToRegsMap amd64_regs{{// GPRs specific to amd64
200349cc55cSDimitry Andric                                  GPR64(8), GPR64(9), GPR64(10), GPR64(11),
201349cc55cSDimitry Andric                                  GPR64(12), GPR64(13), GPR64(14), GPR64(15),
202349cc55cSDimitry Andric 
203349cc55cSDimitry Andric                                  // higher YMM registers (specific to amd64)
204349cc55cSDimitry Andric                                  YMM(8), YMM(9), YMM(10), YMM(11), YMM(12),
205349cc55cSDimitry Andric                                  YMM(13), YMM(14), YMM(15)}};
206349cc55cSDimitry Andric     out.insert(amd64_regs.begin(), amd64_regs.end());
207349cc55cSDimitry Andric   }
208349cc55cSDimitry Andric 
209349cc55cSDimitry Andric   return out;
210349cc55cSDimitry Andric }
211349cc55cSDimitry Andric 
AugmentRegisterInfo(std::vector<DynamicRegisterInfo::Register> & regs)212349cc55cSDimitry Andric void ABIX86::AugmentRegisterInfo(
213349cc55cSDimitry Andric     std::vector<DynamicRegisterInfo::Register> &regs) {
214349cc55cSDimitry Andric   MCBasedABI::AugmentRegisterInfo(regs);
215349cc55cSDimitry Andric 
216349cc55cSDimitry Andric   ProcessSP process_sp = GetProcessSP();
217349cc55cSDimitry Andric   if (!process_sp)
218349cc55cSDimitry Andric     return;
219349cc55cSDimitry Andric 
220349cc55cSDimitry Andric   uint32_t gpr_base_size =
221349cc55cSDimitry Andric       process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
222349cc55cSDimitry Andric 
223349cc55cSDimitry Andric   // primary map from a base register to its subregisters
224349cc55cSDimitry Andric   BaseRegToRegsMap base_reg_map = makeBaseRegMap(gpr_base_size == 8);
225349cc55cSDimitry Andric   // set used for fast matching of register names to subregisters
226349cc55cSDimitry Andric   llvm::SmallDenseSet<llvm::StringRef, 64> subreg_name_set;
227349cc55cSDimitry Andric   // convenience array providing access to all subregisters of given kind,
228349cc55cSDimitry Andric   // sorted by base register index
229349cc55cSDimitry Andric   std::array<llvm::SmallVector<RegData *, 16>, RegKindCount> subreg_by_kind;
230349cc55cSDimitry Andric 
231349cc55cSDimitry Andric   // prepare the set of all known subregisters
232349cc55cSDimitry Andric   for (const auto &x : base_reg_map) {
233349cc55cSDimitry Andric     for (const auto &subreg : x.second)
234349cc55cSDimitry Andric       subreg_name_set.insert(subreg.subreg_name);
235349cc55cSDimitry Andric   }
236349cc55cSDimitry Andric 
237349cc55cSDimitry Andric   // iterate over all registers
238349cc55cSDimitry Andric   for (const auto &x : llvm::enumerate(regs)) {
239349cc55cSDimitry Andric     llvm::StringRef reg_name = x.value().name.GetStringRef();
240349cc55cSDimitry Andric     // abort if at least one sub-register is already present
241349cc55cSDimitry Andric     if (llvm::is_contained(subreg_name_set, reg_name))
242349cc55cSDimitry Andric       return;
243349cc55cSDimitry Andric 
244349cc55cSDimitry Andric     auto found = base_reg_map.find(reg_name);
245349cc55cSDimitry Andric     if (found == base_reg_map.end())
246349cc55cSDimitry Andric       continue;
247349cc55cSDimitry Andric 
248349cc55cSDimitry Andric     for (auto &subreg : found->second) {
249349cc55cSDimitry Andric       // fill in base register indices
250349cc55cSDimitry Andric       subreg.base_index = x.index();
251349cc55cSDimitry Andric       // fill subreg_by_kind map-array
252349cc55cSDimitry Andric       subreg_by_kind[static_cast<size_t>(subreg.subreg_kind)].push_back(
253349cc55cSDimitry Andric           &subreg);
254349cc55cSDimitry Andric     }
255349cc55cSDimitry Andric   }
256349cc55cSDimitry Andric 
257349cc55cSDimitry Andric   // now add registers by kind
258349cc55cSDimitry Andric   addPartialRegisters(regs, subreg_by_kind[GPR32], gpr_base_size, eEncodingUint,
259349cc55cSDimitry Andric                       eFormatHex, 4);
260349cc55cSDimitry Andric   addPartialRegisters(regs, subreg_by_kind[GPR16], gpr_base_size, eEncodingUint,
261349cc55cSDimitry Andric                       eFormatHex, 2);
262349cc55cSDimitry Andric   addPartialRegisters(regs, subreg_by_kind[GPR8h], gpr_base_size, eEncodingUint,
263349cc55cSDimitry Andric                       eFormatHex, 1, 1);
264349cc55cSDimitry Andric   addPartialRegisters(regs, subreg_by_kind[GPR8], gpr_base_size, eEncodingUint,
265349cc55cSDimitry Andric                       eFormatHex, 1);
266349cc55cSDimitry Andric 
267349cc55cSDimitry Andric   addPartialRegisters(regs, subreg_by_kind[MM], 10, eEncodingUint, eFormatHex,
268349cc55cSDimitry Andric                       8);
269349cc55cSDimitry Andric 
270349cc55cSDimitry Andric   addCombinedRegisters(regs, subreg_by_kind[YMM_XMM], subreg_by_kind[YMM_YMMh],
271349cc55cSDimitry Andric                        16, eEncodingVector, eFormatVectorOfUInt8);
2725ffd83dbSDimitry Andric }
273