]>
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" | |
f49ff000 YQ |
24 | |
25 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
26 | #include "../features/i386/32bit-core.c" | |
27 | #include "../features/i386/32bit-linux.c" | |
28 | #include "../features/i386/32bit-sse.c" | |
29 | #include "../features/i386/32bit-avx.c" | |
30 | #include "../features/i386/32bit-avx512.c" | |
31 | #include "../features/i386/32bit-mpx.c" | |
32 | #include "../features/i386/32bit-pkeys.c" | |
33 | ||
34 | /* Defined in auto-generated file i386-linux.c. */ | |
35 | void init_registers_i386_linux (void); | |
36 | extern const struct target_desc *tdesc_i386_linux; | |
37 | ||
38 | /* Defined in auto-generated file i386-mmx-linux.c. */ | |
39 | void init_registers_i386_mmx_linux (void); | |
40 | extern const struct target_desc *tdesc_i386_mmx_linux; | |
41 | ||
42 | /* Defined in auto-generated file i386-avx-linux.c. */ | |
43 | void init_registers_i386_avx_linux (void); | |
44 | extern const struct target_desc *tdesc_i386_avx_linux; | |
45 | ||
46 | /* Defined in auto-generated file i386-avx-mpx-linux.c. */ | |
47 | void init_registers_i386_avx_mpx_linux (void); | |
48 | extern const struct target_desc *tdesc_i386_avx_mpx_linux; | |
49 | ||
50 | /* Defined in auto-generated file i386-avx-avx512-linux.c. */ | |
51 | void init_registers_i386_avx_avx512_linux (void); | |
52 | extern const struct target_desc *tdesc_i386_avx_avx512_linux; | |
53 | ||
54 | /* Defined in auto-generated file i386-avx-mpx-avx512-linux.c. */ | |
55 | void init_registers_i386_avx_mpx_avx512_pku_linux (void); | |
56 | extern const struct target_desc *tdesc_i386_avx_mpx_avx512_pku_linux; | |
57 | ||
58 | /* Defined in auto-generated file i386-mpx-linux.c. */ | |
59 | void init_registers_i386_mpx_linux (void); | |
60 | extern const struct target_desc *tdesc_i386_mpx_linux; | |
61 | #endif | |
62 | ||
63 | static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; | |
64 | ||
0a188386 YQ |
65 | #if defined GDB_SELF_TEST && !defined IN_PROCESS_AGENT |
66 | #include "selftest.h" | |
67 | ||
68 | namespace selftests { | |
69 | namespace tdesc { | |
70 | static void | |
71 | i386_tdesc_test () | |
72 | { | |
73 | struct | |
74 | { | |
75 | unsigned int mask; | |
76 | const target_desc *tdesc; | |
77 | } tdesc_tests[] = { | |
78 | { X86_XSTATE_X87, tdesc_i386_mmx_linux }, | |
79 | { X86_XSTATE_SSE_MASK, tdesc_i386_linux }, | |
80 | { X86_XSTATE_AVX_MASK, tdesc_i386_avx_linux }, | |
81 | { X86_XSTATE_MPX_MASK, tdesc_i386_mpx_linux }, | |
82 | { X86_XSTATE_AVX_MPX_MASK, tdesc_i386_avx_mpx_linux }, | |
83 | { X86_XSTATE_AVX_AVX512_MASK, tdesc_i386_avx_avx512_linux }, | |
84 | { X86_XSTATE_AVX_MPX_AVX512_PKU_MASK, tdesc_i386_avx_mpx_avx512_pku_linux } | |
85 | }; | |
86 | ||
87 | for (auto &elem : tdesc_tests) | |
88 | { | |
89 | const target_desc *tdesc = i386_linux_read_description (elem.mask); | |
90 | ||
91 | SELF_CHECK (*tdesc == *elem.tdesc); | |
92 | } | |
93 | } | |
94 | } | |
95 | } // namespace selftests | |
96 | #endif /* GDB_SELF_TEST */ | |
97 | ||
f49ff000 YQ |
98 | void |
99 | initialize_low_tdesc () | |
100 | { | |
101 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
102 | init_registers_i386_linux (); | |
103 | init_registers_i386_mmx_linux (); | |
104 | init_registers_i386_avx_linux (); | |
105 | init_registers_i386_mpx_linux (); | |
106 | init_registers_i386_avx_mpx_linux (); | |
107 | init_registers_i386_avx_avx512_linux (); | |
108 | init_registers_i386_avx_mpx_avx512_pku_linux (); | |
0a188386 YQ |
109 | |
110 | #if GDB_SELF_TEST && !defined IN_PROCESS_AGENT | |
111 | selftests::register_test (selftests::tdesc::i386_tdesc_test); | |
112 | #endif | |
f49ff000 YQ |
113 | #endif |
114 | } | |
115 | ||
116 | #if defined __i386__ || !defined IN_PROCESS_AGENT | |
117 | ||
118 | /* Return the target description according to XCR0. */ | |
119 | ||
120 | const struct target_desc * | |
121 | i386_linux_read_description (uint64_t xcr0) | |
122 | { | |
123 | struct target_desc **tdesc = NULL; | |
124 | ||
125 | if (xcr0 & X86_XSTATE_PKRU) | |
126 | tdesc = &i386_tdescs[X86_TDESC_AVX_MPX_AVX512_PKU]; | |
127 | else if (xcr0 & X86_XSTATE_AVX512) | |
128 | tdesc = &i386_tdescs[X86_TDESC_AVX_AVX512]; | |
129 | else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) | |
130 | tdesc = &i386_tdescs[X86_TDESC_AVX_MPX]; | |
131 | else if (xcr0 & X86_XSTATE_MPX) | |
132 | tdesc = &i386_tdescs[X86_TDESC_MPX]; | |
133 | else if (xcr0 & X86_XSTATE_AVX) | |
134 | tdesc = &i386_tdescs[X86_TDESC_AVX]; | |
135 | else if (xcr0 & X86_XSTATE_SSE) | |
136 | tdesc = &i386_tdescs[X86_TDESC_SSE]; | |
137 | else if (xcr0 & X86_XSTATE_X87) | |
138 | tdesc = &i386_tdescs[X86_TDESC_MMX]; | |
139 | ||
140 | if (tdesc == NULL) | |
141 | return NULL; | |
142 | ||
143 | if (*tdesc == NULL) | |
144 | { | |
145 | *tdesc = new target_desc (); | |
146 | ||
0abe8a89 YQ |
147 | #ifndef IN_PROCESS_AGENT |
148 | set_tdesc_architecture (*tdesc, "i386"); | |
149 | set_tdesc_osabi (*tdesc, "GNU/Linux"); | |
150 | #endif | |
151 | ||
f49ff000 YQ |
152 | long regnum = 0; |
153 | ||
154 | if (xcr0 & X86_XSTATE_X87) | |
155 | regnum = create_feature_i386_32bit_core (*tdesc, regnum); | |
156 | ||
157 | if (xcr0 & X86_XSTATE_SSE) | |
158 | regnum = create_feature_i386_32bit_sse (*tdesc, regnum); | |
159 | ||
160 | regnum = create_feature_i386_32bit_linux (*tdesc, regnum); | |
161 | ||
162 | if (xcr0 & X86_XSTATE_AVX) | |
163 | regnum = create_feature_i386_32bit_avx (*tdesc, regnum); | |
164 | ||
165 | if (xcr0 & X86_XSTATE_MPX) | |
166 | regnum = create_feature_i386_32bit_mpx (*tdesc, regnum); | |
167 | ||
168 | if (xcr0 & X86_XSTATE_AVX512) | |
169 | regnum = create_feature_i386_32bit_avx512 (*tdesc, regnum); | |
170 | ||
171 | if (xcr0 & X86_XSTATE_PKRU) | |
172 | regnum = create_feature_i386_32bit_pkeys (*tdesc, regnum); | |
173 | ||
174 | init_target_desc (*tdesc); | |
175 | ||
176 | #ifndef IN_PROCESS_AGENT | |
177 | static const char *expedite_regs_i386[] = { "ebp", "esp", "eip", NULL }; | |
178 | (*tdesc)->expedite_regs = expedite_regs_i386; | |
f49ff000 YQ |
179 | #endif |
180 | } | |
181 | ||
182 | return *tdesc;; | |
183 | } | |
184 | #endif | |
185 | ||
186 | #ifndef IN_PROCESS_AGENT | |
187 | int | |
188 | i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) | |
189 | { | |
190 | for (int i = 0; i < X86_TDESC_LAST; i++) | |
191 | { | |
192 | if (tdesc == i386_tdescs[i]) | |
193 | return i; | |
194 | } | |
195 | ||
196 | /* If none tdesc is found, return the one with minimum features. */ | |
197 | return X86_TDESC_MMX; | |
198 | } | |
199 | ||
200 | #endif |