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, 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, 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, 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     nullptr,                                                                   \
99   }
100 
101 #define DEFINE_XMM(reg, i)                                                     \
102   {                                                                            \
103     #reg #i, nullptr, XMM_SIZE,                                                \
104         LLVM_EXTENSION FPR_OFFSET(                                             \
105             reg[i]), eEncodingVector, eFormatVectorOfUInt8,                    \
106             {ehframe_##reg##i##_i386, dwarf_##reg##i##_i386,                   \
107              LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 }, \
108              nullptr, nullptr, nullptr,                                        \
109   }
110 
111 // I believe the YMM registers use dwarf_xmm_%_i386 register numbers and then
112 // differentiate based on register size.
113 #define DEFINE_YMM(reg, i)                                                     \
114   {                                                                            \
115     #reg #i, nullptr, YMM_SIZE,                                                \
116         LLVM_EXTENSION YMM_OFFSET(i), eEncodingVector, eFormatVectorOfUInt8,   \
117                                   {LLDB_INVALID_REGNUM, dwarf_xmm##i##_i386,   \
118                                    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,   \
119                                    lldb_##reg##i##_i386 },                     \
120                                    nullptr, nullptr, nullptr,                  \
121   }
122 
123 #define DEFINE_BNDR(reg, i)                                                    \
124   {                                                                            \
125     #reg #i, nullptr, BNDR_SIZE,                                               \
126         LLVM_EXTENSION BNDR_OFFSET(i), eEncodingVector, eFormatVectorOfUInt64, \
127         {dwarf_##reg##i##_i386, dwarf_##reg##i##_i386, LLDB_INVALID_REGNUM,    \
128          LLDB_INVALID_REGNUM, lldb_##reg##i##_i386 },                          \
129          nullptr, nullptr, nullptr,                                            \
130   }
131 
132 #define DEFINE_BNDC(name, i)                                                   \
133   {                                                                            \
134     #name, nullptr, BNDC_SIZE,                                                 \
135            LLVM_EXTENSION BNDC_OFFSET(i), eEncodingVector,                     \
136            eFormatVectorOfUInt8,                                               \
137            {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,     \
138             LLDB_INVALID_REGNUM, lldb_##name##_i386 },                         \
139             nullptr, nullptr, nullptr,                                         \
140   }
141 
142 #define DEFINE_DR(reg, i)                                                      \
143   {                                                                            \
144     #reg #i, nullptr, DR_SIZE,                                                 \
145         DR_OFFSET(i), eEncodingUint, eFormatHex,                               \
146                   {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
147                    LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                   \
148                    lldb_##reg##i##_i386 },                                     \
149                    nullptr, nullptr, nullptr,                                  \
150   }
151 
152 #define DEFINE_GPR_PSEUDO_16(reg16, reg32)                                     \
153   {                                                                            \
154     #reg16, nullptr, 2,                                                        \
155         GPR_OFFSET(reg32), eEncodingUint, eFormatHex,                          \
156                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
157                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
158                     lldb_##reg16##_i386 },                                     \
159                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
160                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
161                     nullptr,                                                   \
162   }
163 
164 #define DEFINE_GPR_PSEUDO_8H(reg8, reg32)                                      \
165   {                                                                            \
166     #reg8, nullptr, 1,                                                         \
167         GPR_OFFSET(reg32) + 1, eEncodingUint, eFormatHex,                      \
168                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
169                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
170                     lldb_##reg8##_i386 },                                      \
171                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
172                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
173                     nullptr,                                                   \
174   }
175 
176 #define DEFINE_GPR_PSEUDO_8L(reg8, reg32)                                      \
177   {                                                                            \
178     #reg8, nullptr, 1,                                                         \
179         GPR_OFFSET(reg32), eEncodingUint, eFormatHex,                          \
180                    {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
181                     LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,                  \
182                     lldb_##reg8##_i386 },                                      \
183                     RegisterContextPOSIX_x86::g_contained_##reg32,             \
184                     RegisterContextPOSIX_x86::g_invalidate_##reg32,            \
185                     nullptr,                                                   \
186   }
187 
188 static RegisterInfo g_register_infos_i386[] = {
189     // General purpose registers.
190     DEFINE_GPR(eax, nullptr, ehframe_eax_i386, dwarf_eax_i386,
191                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
192     DEFINE_GPR(ebx, nullptr, ehframe_ebx_i386, dwarf_ebx_i386,
193                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
194     DEFINE_GPR(ecx, nullptr, ehframe_ecx_i386, dwarf_ecx_i386,
195                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
196     DEFINE_GPR(edx, nullptr, ehframe_edx_i386, dwarf_edx_i386,
197                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
198     DEFINE_GPR(edi, nullptr, ehframe_edi_i386, dwarf_edi_i386,
199                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
200     DEFINE_GPR(esi, nullptr, ehframe_esi_i386, dwarf_esi_i386,
201                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
202     DEFINE_GPR(ebp, "fp", ehframe_ebp_i386, dwarf_ebp_i386,
203                LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM),
204     DEFINE_GPR(esp, "sp", ehframe_esp_i386, dwarf_esp_i386,
205                LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM),
206     DEFINE_GPR(eip, "pc", ehframe_eip_i386, dwarf_eip_i386,
207                LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM),
208     DEFINE_GPR(eflags, "flags", ehframe_eflags_i386, dwarf_eflags_i386,
209                LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM),
210     DEFINE_GPR(cs, nullptr, LLDB_INVALID_REGNUM, dwarf_cs_i386,
211                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
212     DEFINE_GPR(fs, nullptr, LLDB_INVALID_REGNUM, dwarf_fs_i386,
213                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
214     DEFINE_GPR(gs, nullptr, LLDB_INVALID_REGNUM, dwarf_gs_i386,
215                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
216     DEFINE_GPR(ss, nullptr, LLDB_INVALID_REGNUM, dwarf_ss_i386,
217                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
218     DEFINE_GPR(ds, nullptr, LLDB_INVALID_REGNUM, dwarf_ds_i386,
219                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
220     DEFINE_GPR(es, nullptr, LLDB_INVALID_REGNUM, dwarf_es_i386,
221                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
222 
223     DEFINE_GPR_PSEUDO_16(ax, eax), DEFINE_GPR_PSEUDO_16(bx, ebx),
224     DEFINE_GPR_PSEUDO_16(cx, ecx), DEFINE_GPR_PSEUDO_16(dx, edx),
225     DEFINE_GPR_PSEUDO_16(di, edi), DEFINE_GPR_PSEUDO_16(si, esi),
226     DEFINE_GPR_PSEUDO_16(bp, ebp), DEFINE_GPR_PSEUDO_16(sp, esp),
227     DEFINE_GPR_PSEUDO_8H(ah, eax), DEFINE_GPR_PSEUDO_8H(bh, ebx),
228     DEFINE_GPR_PSEUDO_8H(ch, ecx), DEFINE_GPR_PSEUDO_8H(dh, edx),
229     DEFINE_GPR_PSEUDO_8L(al, eax), DEFINE_GPR_PSEUDO_8L(bl, ebx),
230     DEFINE_GPR_PSEUDO_8L(cl, ecx), DEFINE_GPR_PSEUDO_8L(dl, edx),
231 
232     // i387 Floating point registers.
233     DEFINE_FPR(fctrl, fctrl, LLDB_INVALID_REGNUM, dwarf_fctrl_i386,
234                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
235     DEFINE_FPR(fstat, fstat, LLDB_INVALID_REGNUM, dwarf_fstat_i386,
236                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
237     DEFINE_FPR(ftag, ftag, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
238                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
239     DEFINE_FPR(fop, fop, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
240                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
241     DEFINE_FPR(fiseg, ptr.i386_.fiseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
242                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
243     DEFINE_FPR(fioff, ptr.i386_.fioff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
244                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
245     DEFINE_FPR(foseg, ptr.i386_.foseg, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
246                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
247     DEFINE_FPR(fooff, ptr.i386_.fooff, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
248                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
249     DEFINE_FPR(mxcsr, mxcsr, LLDB_INVALID_REGNUM, dwarf_mxcsr_i386,
250                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
251     DEFINE_FPR(mxcsrmask, mxcsrmask, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
252                LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM),
253 
254     // FP registers.
255     DEFINE_FP_ST(st, 0), DEFINE_FP_ST(st, 1), DEFINE_FP_ST(st, 2),
256     DEFINE_FP_ST(st, 3), DEFINE_FP_ST(st, 4), DEFINE_FP_ST(st, 5),
257     DEFINE_FP_ST(st, 6), DEFINE_FP_ST(st, 7),
258 
259     DEFINE_FP_MM(mm, 0, st0), DEFINE_FP_MM(mm, 1, st1),
260     DEFINE_FP_MM(mm, 2, st2), DEFINE_FP_MM(mm, 3, st3),
261     DEFINE_FP_MM(mm, 4, st4), DEFINE_FP_MM(mm, 5, st5),
262     DEFINE_FP_MM(mm, 6, st6), DEFINE_FP_MM(mm, 7, st7),
263 
264     // XMM registers
265     DEFINE_XMM(xmm, 0), DEFINE_XMM(xmm, 1), DEFINE_XMM(xmm, 2),
266     DEFINE_XMM(xmm, 3), DEFINE_XMM(xmm, 4), DEFINE_XMM(xmm, 5),
267     DEFINE_XMM(xmm, 6), DEFINE_XMM(xmm, 7),
268 
269     // Copy of YMM registers assembled from xmm and ymmh
270     DEFINE_YMM(ymm, 0), DEFINE_YMM(ymm, 1), DEFINE_YMM(ymm, 2),
271     DEFINE_YMM(ymm, 3), DEFINE_YMM(ymm, 4), DEFINE_YMM(ymm, 5),
272     DEFINE_YMM(ymm, 6), DEFINE_YMM(ymm, 7),
273 
274     // MPX registers
275     DEFINE_BNDR(bnd, 0),
276     DEFINE_BNDR(bnd, 1),
277     DEFINE_BNDR(bnd, 2),
278     DEFINE_BNDR(bnd, 3),
279 
280     DEFINE_BNDC(bndcfgu, 0),
281     DEFINE_BNDC(bndstatus, 1),
282 
283     // Debug registers for lldb internal use
284     DEFINE_DR(dr, 0), DEFINE_DR(dr, 1), DEFINE_DR(dr, 2), DEFINE_DR(dr, 3),
285     DEFINE_DR(dr, 4), DEFINE_DR(dr, 5), DEFINE_DR(dr, 6), DEFINE_DR(dr, 7)};
286 
287 static_assert((sizeof(g_register_infos_i386) /
288                sizeof(g_register_infos_i386[0])) == k_num_registers_i386,
289               "g_register_infos_x86_64 has wrong number of register infos");
290 
291 #undef GPR_OFFSET
292 #undef FPR_OFFSET
293 #undef YMM_OFFSET
294 #undef FPR_SIZE
295 #undef FP_SIZE
296 #undef XMM_SIZE
297 #undef YMM_SIZE
298 #undef DEFINE_GPR
299 #undef DEFINE_FPR
300 #undef DEFINE_FP
301 #undef DEFINE_XMM
302 #undef DEFINE_YMM
303 #undef DEFINE_BNDR
304 #undef DEFINE_BNDC
305 #undef DEFINE_DR
306 #undef DEFINE_GPR_PSEUDO_16
307 #undef DEFINE_GPR_PSEUDO_8H
308 #undef DEFINE_GPR_PSEUDO_8L
309 
310 #endif // DECLARE_REGISTER_INFOS_I386_STRUCT
311