1 /* GNU/Linux/x86-64 specific target description, for the remote server 2 for GDB. 3 Copyright (C) 2017-2024 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 "tdesc.h" 21 #include "linux-x86-tdesc.h" 22 #include "arch/i386.h" 23 #include "gdbsupport/x86-xstate.h" 24 #ifdef __x86_64__ 25 #include "arch/amd64.h" 26 #endif 27 #include "x86-tdesc.h" 28 29 /* Return the right x86_linux_tdesc index for a given XCR0. Return 30 X86_TDESC_LAST if can't find a match. */ 31 32 static enum x86_linux_tdesc 33 xcr0_to_tdesc_idx (uint64_t xcr0, bool is_x32) 34 { 35 if (xcr0 & X86_XSTATE_PKRU) 36 { 37 if (is_x32) 38 { 39 /* No x32 MPX and PKU, fall back to avx_avx512. */ 40 return X86_TDESC_AVX_AVX512; 41 } 42 else 43 return X86_TDESC_AVX_MPX_AVX512_PKU; 44 } 45 else if (xcr0 & X86_XSTATE_AVX512) 46 return X86_TDESC_AVX_AVX512; 47 else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) 48 { 49 if (is_x32) /* No MPX on x32. */ 50 return X86_TDESC_AVX; 51 else 52 return X86_TDESC_AVX_MPX; 53 } 54 else if (xcr0 & X86_XSTATE_MPX) 55 { 56 if (is_x32) /* No MPX on x32. */ 57 return X86_TDESC_AVX; 58 else 59 return X86_TDESC_MPX; 60 } 61 else if (xcr0 & X86_XSTATE_AVX) 62 return X86_TDESC_AVX; 63 else if (xcr0 & X86_XSTATE_SSE) 64 return X86_TDESC_SSE; 65 else if (xcr0 & X86_XSTATE_X87) 66 return X86_TDESC_MMX; 67 else 68 return X86_TDESC_LAST; 69 } 70 71 #if defined __i386__ || !defined IN_PROCESS_AGENT 72 73 static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; 74 75 /* Return the target description according to XCR0. */ 76 77 const struct target_desc * 78 i386_linux_read_description (uint64_t xcr0) 79 { 80 enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, false); 81 82 if (idx == X86_TDESC_LAST) 83 return NULL; 84 85 struct target_desc **tdesc = &i386_tdescs[idx]; 86 87 if (*tdesc == NULL) 88 { 89 *tdesc = i386_create_target_description (xcr0, true, false); 90 91 init_target_desc (*tdesc, i386_expedite_regs); 92 } 93 94 return *tdesc;; 95 } 96 #endif 97 98 #ifdef __x86_64__ 99 100 static target_desc *amd64_tdescs[X86_TDESC_LAST] = { }; 101 static target_desc *x32_tdescs[X86_TDESC_LAST] = { }; 102 103 const struct target_desc * 104 amd64_linux_read_description (uint64_t xcr0, bool is_x32) 105 { 106 enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, is_x32); 107 108 if (idx == X86_TDESC_LAST) 109 return NULL; 110 111 struct target_desc **tdesc = NULL; 112 113 if (is_x32) 114 tdesc = &x32_tdescs[idx]; 115 else 116 tdesc = &amd64_tdescs[idx]; 117 118 if (*tdesc == NULL) 119 { 120 *tdesc = amd64_create_target_description (xcr0, is_x32, true, true); 121 122 init_target_desc (*tdesc, amd64_expedite_regs); 123 } 124 return *tdesc; 125 } 126 127 #endif 128 129 #ifndef IN_PROCESS_AGENT 130 131 int 132 i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) 133 { 134 for (int i = 0; i < X86_TDESC_LAST; i++) 135 { 136 if (tdesc == i386_tdescs[i]) 137 return i; 138 } 139 140 /* If none tdesc is found, return the one with minimum features. */ 141 return X86_TDESC_MMX; 142 } 143 144 #if defined __x86_64__ 145 int 146 amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc) 147 { 148 for (int i = 0; i < X86_TDESC_LAST; i++) 149 { 150 if (tdesc == amd64_tdescs[i]) 151 return i; 152 } 153 for (int i = 0; i < X86_TDESC_LAST; i++) 154 { 155 if (tdesc == x32_tdescs[i]) 156 return i; 157 } 158 159 return X86_TDESC_SSE; 160 } 161 162 #endif 163 #endif 164