[GDBserver] unit test to i386_tdesc
[external/binutils.git] / gdb / gdbserver / linux-x86-tdesc.c
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
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
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 ();
110
111 #if GDB_SELF_TEST && !defined IN_PROCESS_AGENT
112   selftests::register_test (selftests::tdesc::i386_tdesc_test);
113 #endif
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