Commit | Line | Data |
---|---|---|
f49ff000 YQ |
1 | /* GNU/Linux/x86-64 specific target description, for the remote server |
2 | for GDB. | |
3 | Copyright (C) 2017 Free Software Foundation, Inc. | |
4 | ||
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
20 | #include "server.h" | |
21 | #include "tdesc.h" | |
22 | #include "linux-x86-tdesc.h" | |
23 | #include "x86-xstate.h" | |
24 | #include <inttypes.h> | |
25 | ||
26 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
27 | #include "../features/i386/32bit-core.c" | |
28 | #include "../features/i386/32bit-linux.c" | |
29 | #include "../features/i386/32bit-sse.c" | |
30 | #include "../features/i386/32bit-avx.c" | |
31 | #include "../features/i386/32bit-avx512.c" | |
32 | #include "../features/i386/32bit-mpx.c" | |
33 | #include "../features/i386/32bit-pkeys.c" | |
34 | ||
35 | /* Defined in auto-generated file i386-linux.c. */ | |
36 | void init_registers_i386_linux (void); | |
37 | extern const struct target_desc *tdesc_i386_linux; | |
38 | ||
39 | /* Defined in auto-generated file i386-mmx-linux.c. */ | |
40 | void init_registers_i386_mmx_linux (void); | |
41 | extern const struct target_desc *tdesc_i386_mmx_linux; | |
42 | ||
43 | /* Defined in auto-generated file i386-avx-linux.c. */ | |
44 | void init_registers_i386_avx_linux (void); | |
45 | extern const struct target_desc *tdesc_i386_avx_linux; | |
46 | ||
47 | /* Defined in auto-generated file i386-avx-mpx-linux.c. */ | |
48 | void init_registers_i386_avx_mpx_linux (void); | |
49 | extern const struct target_desc *tdesc_i386_avx_mpx_linux; | |
50 | ||
51 | /* Defined in auto-generated file i386-avx-avx512-linux.c. */ | |
52 | void init_registers_i386_avx_avx512_linux (void); | |
53 | extern const struct target_desc *tdesc_i386_avx_avx512_linux; | |
54 | ||
55 | /* Defined in auto-generated file i386-avx-mpx-avx512-linux.c. */ | |
56 | void init_registers_i386_avx_mpx_avx512_pku_linux (void); | |
57 | extern const struct target_desc *tdesc_i386_avx_mpx_avx512_pku_linux; | |
58 | ||
59 | /* Defined in auto-generated file i386-mpx-linux.c. */ | |
60 | void init_registers_i386_mpx_linux (void); | |
61 | extern const struct target_desc *tdesc_i386_mpx_linux; | |
62 | #endif | |
63 | ||
64 | static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; | |
65 | ||
0a188386 YQ |
66 | #if defined GDB_SELF_TEST && !defined IN_PROCESS_AGENT |
67 | #include "selftest.h" | |
68 | ||
69 | namespace selftests { | |
70 | namespace tdesc { | |
71 | static void | |
72 | i386_tdesc_test () | |
73 | { | |
74 | struct | |
75 | { | |
76 | unsigned int mask; | |
77 | const target_desc *tdesc; | |
78 | } tdesc_tests[] = { | |
79 | { X86_XSTATE_X87, tdesc_i386_mmx_linux }, | |
80 | { X86_XSTATE_SSE_MASK, tdesc_i386_linux }, | |
81 | { X86_XSTATE_AVX_MASK, tdesc_i386_avx_linux }, | |
82 | { X86_XSTATE_MPX_MASK, tdesc_i386_mpx_linux }, | |
83 | { X86_XSTATE_AVX_MPX_MASK, tdesc_i386_avx_mpx_linux }, | |
84 | { X86_XSTATE_AVX_AVX512_MASK, tdesc_i386_avx_avx512_linux }, | |
85 | { X86_XSTATE_AVX_MPX_AVX512_PKU_MASK, tdesc_i386_avx_mpx_avx512_pku_linux } | |
86 | }; | |
87 | ||
88 | for (auto &elem : tdesc_tests) | |
89 | { | |
90 | const target_desc *tdesc = i386_linux_read_description (elem.mask); | |
91 | ||
92 | SELF_CHECK (*tdesc == *elem.tdesc); | |
93 | } | |
94 | } | |
95 | } | |
96 | } // namespace selftests | |
97 | #endif /* GDB_SELF_TEST */ | |
98 | ||
f49ff000 YQ |
99 | void |
100 | initialize_low_tdesc () | |
101 | { | |
102 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
103 | init_registers_i386_linux (); | |
104 | init_registers_i386_mmx_linux (); | |
105 | init_registers_i386_avx_linux (); | |
106 | init_registers_i386_mpx_linux (); | |
107 | init_registers_i386_avx_mpx_linux (); | |
108 | init_registers_i386_avx_avx512_linux (); | |
109 | init_registers_i386_avx_mpx_avx512_pku_linux (); | |
0a188386 YQ |
110 | |
111 | #if GDB_SELF_TEST && !defined IN_PROCESS_AGENT | |
112 | selftests::register_test (selftests::tdesc::i386_tdesc_test); | |
113 | #endif | |
f49ff000 YQ |
114 | #endif |
115 | } | |
116 | ||
117 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
118 | ||
119 | /* Return the target description according to XCR0. */ | |
120 | ||
121 | const struct target_desc * | |
122 | i386_linux_read_description (uint64_t xcr0) | |
123 | { | |
124 | struct target_desc **tdesc = NULL; | |
125 | ||
126 | if (xcr0 & X86_XSTATE_PKRU) | |
127 | tdesc = &i386_tdescs[X86_TDESC_AVX_MPX_AVX512_PKU]; | |
128 | else if (xcr0 & X86_XSTATE_AVX512) | |
129 | tdesc = &i386_tdescs[X86_TDESC_AVX_AVX512]; | |
130 | else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) | |
131 | tdesc = &i386_tdescs[X86_TDESC_AVX_MPX]; | |
132 | else if (xcr0 & X86_XSTATE_MPX) | |
133 | tdesc = &i386_tdescs[X86_TDESC_MPX]; | |
134 | else if (xcr0 & X86_XSTATE_AVX) | |
135 | tdesc = &i386_tdescs[X86_TDESC_AVX]; | |
136 | else if (xcr0 & X86_XSTATE_SSE) | |
137 | tdesc = &i386_tdescs[X86_TDESC_SSE]; | |
138 | else if (xcr0 & X86_XSTATE_X87) | |
139 | tdesc = &i386_tdescs[X86_TDESC_MMX]; | |
140 | ||
141 | if (tdesc == NULL) | |
142 | return NULL; | |
143 | ||
144 | if (*tdesc == NULL) | |
145 | { | |
146 | *tdesc = new target_desc (); | |
147 | ||
148 | long regnum = 0; | |
149 | ||
150 | if (xcr0 & X86_XSTATE_X87) | |
151 | regnum = create_feature_i386_32bit_core (*tdesc, regnum); | |
152 | ||
153 | if (xcr0 & X86_XSTATE_SSE) | |
154 | regnum = create_feature_i386_32bit_sse (*tdesc, regnum); | |
155 | ||
156 | regnum = create_feature_i386_32bit_linux (*tdesc, regnum); | |
157 | ||
158 | if (xcr0 & X86_XSTATE_AVX) | |
159 | regnum = create_feature_i386_32bit_avx (*tdesc, regnum); | |
160 | ||
161 | if (xcr0 & X86_XSTATE_MPX) | |
162 | regnum = create_feature_i386_32bit_mpx (*tdesc, regnum); | |
163 | ||
164 | if (xcr0 & X86_XSTATE_AVX512) | |
165 | regnum = create_feature_i386_32bit_avx512 (*tdesc, regnum); | |
166 | ||
167 | if (xcr0 & X86_XSTATE_PKRU) | |
168 | regnum = create_feature_i386_32bit_pkeys (*tdesc, regnum); | |
169 | ||
170 | init_target_desc (*tdesc); | |
171 | ||
172 | #ifndef IN_PROCESS_AGENT | |
173 | static const char *expedite_regs_i386[] = { "ebp", "esp", "eip", NULL }; | |
174 | (*tdesc)->expedite_regs = expedite_regs_i386; | |
175 | ||
176 | if (xcr0 & X86_XSTATE_PKRU) | |
177 | (*tdesc)->xmltarget = "i386-avx-mpx-avx512-pku-linux.xml"; | |
178 | else if (xcr0 & X86_XSTATE_AVX512) | |
179 | (*tdesc)->xmltarget = "i386-avx-avx512-linux.xml"; | |
180 | else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) | |
181 | (*tdesc)->xmltarget = "i386-avx-mpx-linux.xml"; | |
182 | else if (xcr0 & X86_XSTATE_MPX) | |
183 | (*tdesc)->xmltarget = "i386-mpx-linux.xml"; | |
184 | else if (xcr0 & X86_XSTATE_AVX) | |
185 | (*tdesc)->xmltarget = "i386-avx-linux.xml"; | |
186 | else if (xcr0 & X86_XSTATE_SSE) | |
187 | (*tdesc)->xmltarget = "i386-linux.xml"; | |
188 | else if (xcr0 & X86_XSTATE_X87) | |
189 | (*tdesc)->xmltarget = "i386-mmx-linux.xml"; | |
190 | else | |
191 | internal_error (__FILE__, __LINE__, | |
192 | "unknown xcr0: %" PRIu64, xcr0); | |
193 | #endif | |
194 | } | |
195 | ||
196 | return *tdesc;; | |
197 | } | |
198 | #endif | |
199 | ||
200 | #ifndef IN_PROCESS_AGENT | |
201 | int | |
202 | i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) | |
203 | { | |
204 | for (int i = 0; i < X86_TDESC_LAST; i++) | |
205 | { | |
206 | if (tdesc == i386_tdescs[i]) | |
207 | return i; | |
208 | } | |
209 | ||
210 | /* If none tdesc is found, return the one with minimum features. */ | |
211 | return X86_TDESC_MMX; | |
212 | } | |
213 | ||
214 | #endif |