1 //===-- RegisterInfos_i386.h ------------------------------------*- C++ -*-===//
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 "llvm/Support/Compiler.h"
10 #include <cstddef>
11 #include <cstdint>
12 
13 
14 #ifdef DECLARE_REGISTER_INFOS_I386_STRUCT
15 
16 // Computes the offset of the given GPR in the user data area.
17 #define GPR_OFFSET(regname) (LLVM_EXTENSION offsetof(GPR, regname))
18 
19 // Computes the offset of the given FPR in the extended data area.
20 #define FPR_OFFSET(regname)                                                    \
21   (LLVM_EXTENSION offsetof(UserArea, i387) +                                   \
22    LLVM_EXTENSION offsetof(FPR_i386, regname))
23 
24 // Computes the offset of the YMM register assembled from register halves.
25 // Based on DNBArchImplI386.cpp from debugserver
26 #define YMM_OFFSET(reg_index)                                                  \
27   (LLVM_EXTENSION offsetof(UserArea, i387) +                                   \
28    LLVM_EXTENSION offsetof(FPR, fxsave) +                                      \
29    LLVM_EXTENSION offsetof(FXSAVE, xmm[7]) + sizeof(XMMReg) +                  \
30    (32 * reg_index))
31 
32 #define BNDR_OFFSET(reg_index)                                                 \
33   (LLVM_EXTENSION offsetof(UserArea, i387) +                                   \
34    LLVM_EXTENSION offsetof(FPR, xsave) +                                       \
35    LLVM_EXTENSION offsetof(XSAVE, mpxr[reg_index]))
36 
37 #define BNDC_OFFSET(reg_index)                                                 \
38   (LLVM_EXTENSION offsetof(UserArea, i387) +                                   \
39    LLVM_EXTENSION offsetof(FPR, xsave) +                                       \
40    LLVM_EXTENSION offsetof(XSAVE, mpxc[reg_index]))
41 
42 // Number of bytes needed to represent a FPR.
43 #if !defined(FPR_SIZE)
44 #define FPR_SIZE(reg) sizeof(((FXSAVE *)nullptr)->reg)
45 #endif
46 
47 // Number of bytes needed to represent the i'th FP register.
48 #define FP_SIZE sizeof(((MMSReg *)nullptr)->bytes)
49 
50 // Number of bytes needed to represent an XMM register.
51 #define XMM_SIZE sizeof(XMMReg)
52 
53 // Number of bytes needed to represent a YMM register.
54 #define YMM_SIZE sizeof(YMMReg)
55 
56 // Number of bytes needed to represent MPX registers.
57 #define BNDR_SIZE sizeof(MPXReg)
58 #define BNDC_SIZE sizeof(MPXCsr)
59 
60 // Note that the size and offset will be updated by platform-specific classes.
61 #define DEFINE_GPR(reg, alt, kind1, kind2, kind3, kind4)                       \
62   {                                                                            \
63     #reg, alt, sizeof(((GPR *)nullptr)->reg),                                  \
64                       GPR_OFFSET(reg), eEncodingUint, eFormatHex,              \
65                                  {kind1, kind2, kind3, kind4,                  \
66                                   lldb_##reg##_i386 },                         \
67                                   nullptr, nullptr,                            \
68   }
69 
70 #define DEFINE_FPR(name, reg, kind1, kind2, kind3, kind4)                      \
71   {                                                                            \
72     #name, nullptr, FPR_SIZE(reg), FPR_OFFSET(reg), eEncodingUint, eFormatHex, \
73                                            {kind1, kind2, kind3, kind4,        \
74                                             lldb_##name##_i386 },              \
75                                             nullptr, nullptr,                  \
76   }
77 
78 // RegisterKind: EHFrame, DWARF, Generic, Process Plugin, LLDB
79 
80 #define DEFINE_FP_ST(reg, i)                                                   \
81   {                                                                            \
82     #reg #i, nullptr, FP_SIZE,                                                 \
83         LLVM_EXTENSION FPR_OFFSET(                                             \
84             stmm[i]), eEncodingVector, eFormatVectorOfUInt8,                   \
85             {ehframe_st##i##_i386, dwarf_st##i##_i386, LLDB_INVALID_REGNUM,    \
86              LLDB_INVALID_REGNUM, lldb_st##i##_i386 },                         \
87              nullptr, nullptr,                                                 \
88   }
89 
90 #define DEFINE_FP_MM(reg, i, streg)                                            \
91   {                                                                            \
92     #reg #i, nullptr, sizeof(uint64_t), LLVM_EXTENSION FPR_OFFSET(stmm[i]),    \
93     eEncodingUint, eFormatHex,                                                 \
94     {dwarf_mm##i##_i386, dwarf_mm##i##_i386, LLDB_INVALID_REGNUM,              \
95      LLDB_INVALID_REGNUM, lldb_mm##i##_i386 },                                 \
96     RegisterContextPOSIX_x86::g_contained_##streg##_32,                        \
97     RegisterContextPOSIX_x86::g_invalidate_##streg##_32,                       \
98   }
99 
100 #define DEFINE_XMM(reg, i)                                                     \
101   {                                                                            \
102     #reg #i, nullptr, XMM_SIZE,                                                \
103         LLVM_EXTENSION FPR_OFFSET(                                             \
104             reg[i]), eEncodingVector, eFormatVectorOfUInt8,                    \
105             {ehframe_##reg##i##_i386, dwarf_##reg##i##_i386,                   \
106              LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \
107              nullptr, nullptr,                                                 \
108   }
109 
110 // I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then
111 // differentiate based on register size.
112 #define DEFINE_YMM(reg, i)                                                     \
113   {                                                                            \
114     #reg #i, nullptr, YMM_SIZE,                                                \
115         LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8,   \
116                                   {LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386,   \
117                                    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   \
118                                    lldb_##reg##i##_i386 },                     \
119                                    nullptr, nullptr,                           \
120   }
121 
122 #define DEFINE_BNDR(reg, i)                                                    \
123   {                                                                            \
124     #reg #i, nullptr, BNDR_SIZE,                                               \
125         LLVM_EXTENSION BNDR_OFFSET(i), eEncodingVector, eFormatVectorOfUInt64, \
126         {dwarf_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM,    \
127          LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 },                          \
128          nullptr, nullptr,                                                     \
129   }
130 
131 #define DEFINE_BNDC(name, i)                                                   \
132   {                                                                            \
133     #name, nullptr, BNDC_SIZE,                                                 \
134            LLVM_EXTENSION BNDC_OFFSET(i), eEncodingVector,                     \
135            eFormatVectorOfUInt8,                                               \
136            {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,     \
137             LLDB_INVALID_REGNUM, lldb_##name##_i386 },                         \
138             nullptr, nullptr,                                                  \
139   }
140 
141 #define DEFINE_DR(reg, i)                                                      \
142   {                                                                            \
143     #reg #i, nullptr, DR_SIZE,                                                 \
144         DR_OFFSET(i), eEncodingUint, eFormatHex,                               \
145                   {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
146                    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
147                    lldb_##reg##i##_i386 },                                     \
148                    nullptr, nullptr,                                           \
149   }
150 
151 #define DEFINE_GPR_PSEUDO_16(reg16, reg32)                                     \
152   {                                                                            \
153     #reg16, nullptr, 2,                                                        \
154         GPR_OFFSET(reg32), eEncodingUint, eFormatHex,                          \
155                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
156                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
157                     lldb_##reg16##_i386 },                                     \
158                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
159                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
160   }
161 
162 #define DEFINE_GPR_PSEUDO_8H(reg8, reg32)                                      \
163   {                                                                            \
164     #reg8, nullptr, 1,                                                         \
165         GPR_OFFSET(reg32) + 1, eEncodingUint, eFormatHex,                      \
166                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
167                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
168                     lldb_##reg8##_i386 },                                      \
169                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
170                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
171   }
172 
173 #define DEFINE_GPR_PSEUDO_8L(reg8, reg32)                                      \
174   {                                                                            \
175     #reg8, nullptr, 1,                                                         \
176         GPR_OFFSET(reg32), eEncodingUint, eFormatHex,                          \
177                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
178                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
179                     lldb_##reg8##_i386 },                                      \
180                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
181                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
182   }
183 
184 static RegisterInfo g_register_infos_i386[] = {
185     // General purpose registers.
186     DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386,
187                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
188     DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386,
189                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
190     DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386,
191                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
192     DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386,
193                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
194     DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386,
195                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
196     DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386,
197                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
198     DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386,
199                LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
200     DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386,
201                LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
202     DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386,
203                LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
204     DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386,
205                LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
206     DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386,
207                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
208     DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386,
209                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
210     DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386,
211                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
212     DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386,
213                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
214     DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386,
215                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
216     DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386,
217                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
218 
219     DEFINE_GPR_PSEUDO_16(ax, eax), DEFINE_GPR_PSEUDO_16(bx, ebx),
220     DEFINE_GPR_PSEUDO_16(cx, ecx), DEFINE_GPR_PSEUDO_16(dx, edx),
221     DEFINE_GPR_PSEUDO_16(di, edi), DEFINE_GPR_PSEUDO_16(si, esi),
222     DEFINE_GPR_PSEUDO_16(bp, ebp), DEFINE_GPR_PSEUDO_16(sp, esp),
223     DEFINE_GPR_PSEUDO_8H(ah, eax), DEFINE_GPR_PSEUDO_8H(bh, ebx),
224     DEFINE_GPR_PSEUDO_8H(ch, ecx), DEFINE_GPR_PSEUDO_8H(dh, edx),
225     DEFINE_GPR_PSEUDO_8L(al, eax), DEFINE_GPR_PSEUDO_8L(bl, ebx),
226     DEFINE_GPR_PSEUDO_8L(cl, ecx), DEFINE_GPR_PSEUDO_8L(dl, edx),
227 
228     // i387 Floating point registers.
229     DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386,
230                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
231     DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386,
232                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
233     DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
234                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
235     DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
236                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
237     DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
238                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
239     DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
240                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
241     DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
242                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
243     DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
244                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
245     DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386,
246                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
247     DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
248                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
249 
250     // FP registers.
251     DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2),
252     DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5),
253     DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7),
254 
255     DEFINE_FP_MM(mm, 0, st0), DEFINE_FP_MM(mm, 1, st1),
256     DEFINE_FP_MM(mm, 2, st2), DEFINE_FP_MM(mm, 3, st3),
257     DEFINE_FP_MM(mm, 4, st4), DEFINE_FP_MM(mm, 5, st5),
258     DEFINE_FP_MM(mm, 6, st6), DEFINE_FP_MM(mm, 7, st7),
259 
260     // XMM registers
261     DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2),
262     DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5),
263     DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7),
264 
265     // Copy of YMM registers assembled from xmm and ymmh
266     DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2),
267     DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5),
268     DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7),
269 
270     // MPX registers
271     DEFINE_BNDR(bnd, 0),
272     DEFINE_BNDR(bnd, 1),
273     DEFINE_BNDR(bnd, 2),
274     DEFINE_BNDR(bnd, 3),
275 
276     DEFINE_BNDC(bndcfgu, 0),
277     DEFINE_BNDC(bndstatus, 1),
278 
279     // Debug registers for lldb internal use
280     DEFINE_DR(dr, 0), DEFINE_DR(dr, 1), DEFINE_DR(dr, 2), DEFINE_DR(dr, 3),
281     DEFINE_DR(dr, 4), DEFINE_DR(dr, 5), DEFINE_DR(dr, 6), DEFINE_DR(dr, 7)};
282 
283 static_assert((sizeof(g_register_infos_i386) /
284                sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
285               "g_register_infos_x86_64 has wrong number of register infos");
286 
287 #undef GPR_OFFSET
288 #undef FPR_OFFSET
289 #undef YMM_OFFSET
290 #undef FPR_SIZE
291 #undef FP_SIZE
292 #undef XMM_SIZE
293 #undef YMM_SIZE
294 #undef DEFINE_GPR
295 #undef DEFINE_FPR
296 #undef DEFINE_FP
297 #undef DEFINE_XMM
298 #undef DEFINE_YMM
299 #undef DEFINE_BNDR
300 #undef DEFINE_BNDC
301 #undef DEFINE_DR
302 #undef DEFINE_GPR_PSEUDO_16
303 #undef DEFINE_GPR_PSEUDO_8H
304 #undef DEFINE_GPR_PSEUDO_8L
305 
306 #endif // DECLARE_REGISTER_INFOS_I386_STRUCT
307