18dffb485Schristos /* GNU/Linux/x86-64 specific target description, for the remote server 28dffb485Schristos for GDB. 3*64f917f5Schristos Copyright (C) 2017-2024 Free Software Foundation, Inc. 48dffb485Schristos 58dffb485Schristos This file is part of GDB. 68dffb485Schristos 78dffb485Schristos This program is free software; you can redistribute it and/or modify 88dffb485Schristos it under the terms of the GNU General Public License as published by 98dffb485Schristos the Free Software Foundation; either version 3 of the License, or 108dffb485Schristos (at your option) any later version. 118dffb485Schristos 128dffb485Schristos This program is distributed in the hope that it will be useful, 138dffb485Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 148dffb485Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 158dffb485Schristos GNU General Public License for more details. 168dffb485Schristos 178dffb485Schristos You should have received a copy of the GNU General Public License 188dffb485Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 198dffb485Schristos 208dffb485Schristos #include "tdesc.h" 218dffb485Schristos #include "linux-x86-tdesc.h" 228dffb485Schristos #include "arch/i386.h" 238dffb485Schristos #include "gdbsupport/x86-xstate.h" 248dffb485Schristos #ifdef __x86_64__ 258dffb485Schristos #include "arch/amd64.h" 268dffb485Schristos #endif 278dffb485Schristos #include "x86-tdesc.h" 288dffb485Schristos 298dffb485Schristos /* Return the right x86_linux_tdesc index for a given XCR0. Return 308dffb485Schristos X86_TDESC_LAST if can't find a match. */ 318dffb485Schristos 328dffb485Schristos static enum x86_linux_tdesc 338dffb485Schristos xcr0_to_tdesc_idx (uint64_t xcr0, bool is_x32) 348dffb485Schristos { 358dffb485Schristos if (xcr0 & X86_XSTATE_PKRU) 368dffb485Schristos { 378dffb485Schristos if (is_x32) 388dffb485Schristos { 398dffb485Schristos /* No x32 MPX and PKU, fall back to avx_avx512. */ 408dffb485Schristos return X86_TDESC_AVX_AVX512; 418dffb485Schristos } 428dffb485Schristos else 438dffb485Schristos return X86_TDESC_AVX_MPX_AVX512_PKU; 448dffb485Schristos } 458dffb485Schristos else if (xcr0 & X86_XSTATE_AVX512) 468dffb485Schristos return X86_TDESC_AVX_AVX512; 478dffb485Schristos else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) 488dffb485Schristos { 498dffb485Schristos if (is_x32) /* No MPX on x32. */ 508dffb485Schristos return X86_TDESC_AVX; 518dffb485Schristos else 528dffb485Schristos return X86_TDESC_AVX_MPX; 538dffb485Schristos } 548dffb485Schristos else if (xcr0 & X86_XSTATE_MPX) 558dffb485Schristos { 568dffb485Schristos if (is_x32) /* No MPX on x32. */ 578dffb485Schristos return X86_TDESC_AVX; 588dffb485Schristos else 598dffb485Schristos return X86_TDESC_MPX; 608dffb485Schristos } 618dffb485Schristos else if (xcr0 & X86_XSTATE_AVX) 628dffb485Schristos return X86_TDESC_AVX; 638dffb485Schristos else if (xcr0 & X86_XSTATE_SSE) 648dffb485Schristos return X86_TDESC_SSE; 658dffb485Schristos else if (xcr0 & X86_XSTATE_X87) 668dffb485Schristos return X86_TDESC_MMX; 678dffb485Schristos else 688dffb485Schristos return X86_TDESC_LAST; 698dffb485Schristos } 708dffb485Schristos 718dffb485Schristos #if defined __i386__ || !defined IN_PROCESS_AGENT 728dffb485Schristos 738dffb485Schristos static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; 748dffb485Schristos 758dffb485Schristos /* Return the target description according to XCR0. */ 768dffb485Schristos 778dffb485Schristos const struct target_desc * 788dffb485Schristos i386_linux_read_description (uint64_t xcr0) 798dffb485Schristos { 808dffb485Schristos enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, false); 818dffb485Schristos 828dffb485Schristos if (idx == X86_TDESC_LAST) 838dffb485Schristos return NULL; 848dffb485Schristos 858dffb485Schristos struct target_desc **tdesc = &i386_tdescs[idx]; 868dffb485Schristos 878dffb485Schristos if (*tdesc == NULL) 888dffb485Schristos { 898dffb485Schristos *tdesc = i386_create_target_description (xcr0, true, false); 908dffb485Schristos 918dffb485Schristos init_target_desc (*tdesc, i386_expedite_regs); 928dffb485Schristos } 938dffb485Schristos 948dffb485Schristos return *tdesc;; 958dffb485Schristos } 968dffb485Schristos #endif 978dffb485Schristos 988dffb485Schristos #ifdef __x86_64__ 998dffb485Schristos 1008dffb485Schristos static target_desc *amd64_tdescs[X86_TDESC_LAST] = { }; 1018dffb485Schristos static target_desc *x32_tdescs[X86_TDESC_LAST] = { }; 1028dffb485Schristos 1038dffb485Schristos const struct target_desc * 1048dffb485Schristos amd64_linux_read_description (uint64_t xcr0, bool is_x32) 1058dffb485Schristos { 1068dffb485Schristos enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, is_x32); 1078dffb485Schristos 1088dffb485Schristos if (idx == X86_TDESC_LAST) 1098dffb485Schristos return NULL; 1108dffb485Schristos 1118dffb485Schristos struct target_desc **tdesc = NULL; 1128dffb485Schristos 1138dffb485Schristos if (is_x32) 1148dffb485Schristos tdesc = &x32_tdescs[idx]; 1158dffb485Schristos else 1168dffb485Schristos tdesc = &amd64_tdescs[idx]; 1178dffb485Schristos 1188dffb485Schristos if (*tdesc == NULL) 1198dffb485Schristos { 1208dffb485Schristos *tdesc = amd64_create_target_description (xcr0, is_x32, true, true); 1218dffb485Schristos 1228dffb485Schristos init_target_desc (*tdesc, amd64_expedite_regs); 1238dffb485Schristos } 1248dffb485Schristos return *tdesc; 1258dffb485Schristos } 1268dffb485Schristos 1278dffb485Schristos #endif 1288dffb485Schristos 1298dffb485Schristos #ifndef IN_PROCESS_AGENT 1308dffb485Schristos 1318dffb485Schristos int 1328dffb485Schristos i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) 1338dffb485Schristos { 1348dffb485Schristos for (int i = 0; i < X86_TDESC_LAST; i++) 1358dffb485Schristos { 1368dffb485Schristos if (tdesc == i386_tdescs[i]) 1378dffb485Schristos return i; 1388dffb485Schristos } 1398dffb485Schristos 1408dffb485Schristos /* If none tdesc is found, return the one with minimum features. */ 1418dffb485Schristos return X86_TDESC_MMX; 1428dffb485Schristos } 1438dffb485Schristos 1448dffb485Schristos #if defined __x86_64__ 1458dffb485Schristos int 1468dffb485Schristos amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc) 1478dffb485Schristos { 1488dffb485Schristos for (int i = 0; i < X86_TDESC_LAST; i++) 1498dffb485Schristos { 1508dffb485Schristos if (tdesc == amd64_tdescs[i]) 1518dffb485Schristos return i; 1528dffb485Schristos } 1538dffb485Schristos for (int i = 0; i < X86_TDESC_LAST; i++) 1548dffb485Schristos { 1558dffb485Schristos if (tdesc == x32_tdescs[i]) 1568dffb485Schristos return i; 1578dffb485Schristos } 1588dffb485Schristos 1598dffb485Schristos return X86_TDESC_SSE; 1608dffb485Schristos } 1618dffb485Schristos 1628dffb485Schristos #endif 1638dffb485Schristos #endif 164