gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / amd64-tdep.c
index 6289d21f3489f61db602579190b1dd9d8c346824..2a0dfed0cd9e650e46c6e2b19bcfce26caca8a00 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-dependent code for AMD64.
 
-   Copyright (C) 2001-2016 Free Software Foundation, Inc.
+   Copyright (C) 2001-2020 Free Software Foundation, Inc.
 
    Contributed by Jiri Smid, SuSE Labs.
 
 #include "disasm.h"
 #include "amd64-tdep.h"
 #include "i387-tdep.h"
-#include "x86-xstate.h"
-
-#include "features/i386/amd64.c"
-#include "features/i386/amd64-avx.c"
-#include "features/i386/amd64-mpx.c"
-#include "features/i386/amd64-avx-mpx.c"
-#include "features/i386/amd64-avx512.c"
-
-#include "features/i386/x32.c"
-#include "features/i386/x32-avx.c"
-#include "features/i386/x32-avx512.c"
-
+#include "gdbsupport/x86-xstate.h"
+#include <algorithm>
+#include "target-descriptions.h"
+#include "arch/amd64.h"
+#include "producer.h"
 #include "ax.h"
 #include "ax-gdb.h"
+#include "gdbsupport/byte-vector.h"
+#include "osabi.h"
+#include "x86-tdep.h"
 
 /* Note that the AMD64 architecture was previously known as x86-64.
    The latter is (forever) engraved into the canonical system name as
@@ -155,6 +151,10 @@ static const char *amd64_xmm_avx512_names[] = {
     "xmm28",  "xmm29",  "xmm30",  "xmm31"
 };
 
+static const char *amd64_pkeys_names[] = {
+    "pkru"
+};
+
 /* DWARF Register Number Mapping as defined in the System V psABI,
    section 3.6.  */
 
@@ -349,19 +349,15 @@ amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum)
 
 static struct value *
 amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
-                                 struct regcache *regcache,
+                                 readable_regcache *regcache,
                                  int regnum)
 {
-  gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  enum register_status status;
-  struct value *result_value;
-  gdb_byte *buf;
 
-  result_value = allocate_value (register_type (gdbarch, regnum));
+  value *result_value = allocate_value (register_type (gdbarch, regnum));
   VALUE_LVAL (result_value) = lval_register;
   VALUE_REGNUM (result_value) = regnum;
-  buf = value_contents_raw (result_value);
+  gdb_byte *buf = value_contents_raw (result_value);
 
   if (i386_byte_regnum_p (gdbarch, regnum))
     {
@@ -370,10 +366,11 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
       /* Extract (always little endian).  */
       if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
        {
+         gpnum -= AMD64_NUM_LOWER_BYTE_REGS;
+         gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
          /* Special handling for AH, BH, CH, DH.  */
-         status = regcache_raw_read (regcache,
-                                     gpnum - AMD64_NUM_LOWER_BYTE_REGS,
-                                     raw_buf);
+         register_status status = regcache->raw_read (gpnum, raw_buf);
          if (status == REG_VALID)
            memcpy (buf, raw_buf + 1, 1);
          else
@@ -382,7 +379,8 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
        }
       else
        {
-         status = regcache_raw_read (regcache, gpnum, raw_buf);
+         gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+         register_status status = regcache->raw_read (gpnum, raw_buf);
          if (status == REG_VALID)
            memcpy (buf, raw_buf, 1);
          else
@@ -393,8 +391,9 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch,
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
       int gpnum = regnum - tdep->eax_regnum;
+      gdb_byte raw_buf[register_size (gdbarch, gpnum)];
       /* Extract (always little endian).  */
-      status = regcache_raw_read (regcache, gpnum, raw_buf);
+      register_status status = regcache->raw_read (gpnum, raw_buf);
       if (status == REG_VALID)
        memcpy (buf, raw_buf, 4);
       else
@@ -413,7 +412,6 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
                             struct regcache *regcache,
                             int regnum, const gdb_byte *buf)
 {
-  gdb_byte raw_buf[MAX_REGISTER_SIZE];
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   if (i386_byte_regnum_p (gdbarch, regnum))
@@ -422,35 +420,39 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch,
 
       if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
        {
+         gpnum -= AMD64_NUM_LOWER_BYTE_REGS;
+         gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
          /* Read ... AH, BH, CH, DH.  */
-         regcache_raw_read (regcache,
-                            gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
+         regcache->raw_read (gpnum, raw_buf);
          /* ... Modify ... (always little endian).  */
          memcpy (raw_buf + 1, buf, 1);
          /* ... Write.  */
-         regcache_raw_write (regcache,
-                             gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
+         regcache->raw_write (gpnum, raw_buf);
        }
       else
        {
+         gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
          /* Read ...  */
-         regcache_raw_read (regcache, gpnum, raw_buf);
+         regcache->raw_read (gpnum, raw_buf);
          /* ... Modify ... (always little endian).  */
          memcpy (raw_buf, buf, 1);
          /* ... Write.  */
-         regcache_raw_write (regcache, gpnum, raw_buf);
+         regcache->raw_write (gpnum, raw_buf);
        }
     }
   else if (i386_dword_regnum_p (gdbarch, regnum))
     {
       int gpnum = regnum - tdep->eax_regnum;
+      gdb_byte raw_buf[register_size (gdbarch, gpnum)];
 
       /* Read ...  */
-      regcache_raw_read (regcache, gpnum, raw_buf);
+      regcache->raw_read (gpnum, raw_buf);
       /* ... Modify ... (always little endian).  */
       memcpy (raw_buf, buf, 4);
       /* ... Write.  */
-      regcache_raw_write (regcache, gpnum, raw_buf);
+      regcache->raw_write (gpnum, raw_buf);
     }
   else
     i386_pseudo_register_write (gdbarch, regcache, regnum, buf);
@@ -539,17 +541,108 @@ amd64_merge_classes (enum amd64_reg_class class1, enum amd64_reg_class class2)
 
 static void amd64_classify (struct type *type, enum amd64_reg_class theclass[2]);
 
-/* Return non-zero if TYPE is a non-POD structure or union type.  */
+/* Return true if TYPE is a structure or union with unaligned fields.  */
 
-static int
-amd64_non_pod_p (struct type *type)
+static bool
+amd64_has_unaligned_fields (struct type *type)
 {
-  /* ??? A class with a base class certainly isn't POD, but does this
-     catch all non-POD structure types?  */
-  if (TYPE_CODE (type) == TYPE_CODE_STRUCT && TYPE_N_BASECLASSES (type) > 0)
-    return 1;
+  if (type->code () == TYPE_CODE_STRUCT
+      || type->code () == TYPE_CODE_UNION)
+    {
+      for (int i = 0; i < type->num_fields (); i++)
+       {
+         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
+         int bitpos = TYPE_FIELD_BITPOS (type, i);
+         int align = type_align(subtype);
+
+         /* Ignore static fields, empty fields (for example nested
+            empty structures), and bitfields (these are handled by
+            the caller).  */
+         if (field_is_static (&type->field (i))
+             || (TYPE_FIELD_BITSIZE (type, i) == 0
+                 && TYPE_LENGTH (subtype) == 0)
+             || TYPE_FIELD_PACKED (type, i))
+           continue;
 
-  return 0;
+         if (bitpos % 8 != 0)
+           return true;
+
+         int bytepos = bitpos / 8;
+         if (bytepos % align != 0)
+           return true;
+
+         if (amd64_has_unaligned_fields (subtype))
+           return true;
+       }
+    }
+
+  return false;
+}
+
+/* Classify field I of TYPE starting at BITOFFSET according to the rules for
+   structures and union types, and store the result in THECLASS.  */
+
+static void
+amd64_classify_aggregate_field (struct type *type, int i,
+                               enum amd64_reg_class theclass[2],
+                               unsigned int bitoffset)
+{
+  struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
+  int bitpos = bitoffset + TYPE_FIELD_BITPOS (type, i);
+  int pos = bitpos / 64;
+  enum amd64_reg_class subclass[2];
+  int bitsize = TYPE_FIELD_BITSIZE (type, i);
+  int endpos;
+
+  if (bitsize == 0)
+    bitsize = TYPE_LENGTH (subtype) * 8;
+  endpos = (bitpos + bitsize - 1) / 64;
+
+  /* Ignore static fields, or empty fields, for example nested
+     empty structures.*/
+  if (field_is_static (&type->field (i)) || bitsize == 0)
+    return;
+
+  if (subtype->code () == TYPE_CODE_STRUCT
+      || subtype->code () == TYPE_CODE_UNION)
+    {
+      /* Each field of an object is classified recursively.  */
+      int j;
+      for (j = 0; j < subtype->num_fields (); j++)
+       amd64_classify_aggregate_field (subtype, j, theclass, bitpos);
+      return;
+    }
+
+  gdb_assert (pos == 0 || pos == 1);
+
+  amd64_classify (subtype, subclass);
+  theclass[pos] = amd64_merge_classes (theclass[pos], subclass[0]);
+  if (bitsize <= 64 && pos == 0 && endpos == 1)
+    /* This is a bit of an odd case:  We have a field that would
+       normally fit in one of the two eightbytes, except that
+       it is placed in a way that this field straddles them.
+       This has been seen with a structure containing an array.
+
+       The ABI is a bit unclear in this case, but we assume that
+       this field's class (stored in subclass[0]) must also be merged
+       into class[1].  In other words, our field has a piece stored
+       in the second eight-byte, and thus its class applies to
+       the second eight-byte as well.
+
+       In the case where the field length exceeds 8 bytes,
+       it should not be necessary to merge the field class
+       into class[1].  As LEN > 8, subclass[1] is necessarily
+       different from AMD64_NO_CLASS.  If subclass[1] is equal
+       to subclass[0], then the normal class[1]/subclass[1]
+       merging will take care of everything.  For subclass[1]
+       to be different from subclass[0], I can only see the case
+       where we have a SSE/SSEUP or X87/X87UP pair, which both
+       use up all 16 bytes of the aggregate, and are already
+       handled just fine (because each portion sits on its own
+       8-byte).  */
+    theclass[1] = amd64_merge_classes (theclass[1], subclass[0]);
+  if (pos == 0)
+    theclass[1] = amd64_merge_classes (theclass[1], subclass[1]);
 }
 
 /* Classify TYPE according to the rules for aggregate (structures and
@@ -558,10 +651,9 @@ amd64_non_pod_p (struct type *type)
 static void
 amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2])
 {
-  /* 1. If the size of an object is larger than two eightbytes, or in
-        C++, is a non-POD structure or union type, or contains
+  /* 1. If the size of an object is larger than two eightbytes, or it has
         unaligned fields, it has class memory.  */
-  if (TYPE_LENGTH (type) > 16 || amd64_non_pod_p (type))
+  if (TYPE_LENGTH (type) > 16 || amd64_has_unaligned_fields (type))
     {
       theclass[0] = theclass[1] = AMD64_MEMORY;
       return;
@@ -575,7 +667,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2])
         calculated according to the classes of the fields in the
         eightbyte: */
 
-  if (TYPE_CODE (type) == TYPE_CODE_ARRAY)
+  if (type->code () == TYPE_CODE_ARRAY)
     {
       struct type *subtype = check_typedef (TYPE_TARGET_TYPE (type));
 
@@ -589,56 +681,11 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2])
       int i;
 
       /* Structure or union.  */
-      gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT
-                 || TYPE_CODE (type) == TYPE_CODE_UNION);
+      gdb_assert (type->code () == TYPE_CODE_STRUCT
+                 || type->code () == TYPE_CODE_UNION);
 
-      for (i = 0; i < TYPE_NFIELDS (type); i++)
-       {
-         struct type *subtype = check_typedef (TYPE_FIELD_TYPE (type, i));
-         int pos = TYPE_FIELD_BITPOS (type, i) / 64;
-         enum amd64_reg_class subclass[2];
-         int bitsize = TYPE_FIELD_BITSIZE (type, i);
-         int endpos;
-
-         if (bitsize == 0)
-           bitsize = TYPE_LENGTH (subtype) * 8;
-         endpos = (TYPE_FIELD_BITPOS (type, i) + bitsize - 1) / 64;
-
-         /* Ignore static fields.  */
-         if (field_is_static (&TYPE_FIELD (type, i)))
-           continue;
-
-         gdb_assert (pos == 0 || pos == 1);
-
-         amd64_classify (subtype, subclass);
-         theclass[pos] = amd64_merge_classes (theclass[pos], subclass[0]);
-         if (bitsize <= 64 && pos == 0 && endpos == 1)
-           /* This is a bit of an odd case:  We have a field that would
-              normally fit in one of the two eightbytes, except that
-              it is placed in a way that this field straddles them.
-              This has been seen with a structure containing an array.
-
-              The ABI is a bit unclear in this case, but we assume that
-              this field's class (stored in subclass[0]) must also be merged
-              into class[1].  In other words, our field has a piece stored
-              in the second eight-byte, and thus its class applies to
-              the second eight-byte as well.
-
-              In the case where the field length exceeds 8 bytes,
-              it should not be necessary to merge the field class
-              into class[1].  As LEN > 8, subclass[1] is necessarily
-              different from AMD64_NO_CLASS.  If subclass[1] is equal
-              to subclass[0], then the normal class[1]/subclass[1]
-              merging will take care of everything.  For subclass[1]
-              to be different from subclass[0], I can only see the case
-              where we have a SSE/SSEUP or X87/X87UP pair, which both
-              use up all 16 bytes of the aggregate, and are already
-              handled just fine (because each portion sits on its own
-              8-byte).  */
-           theclass[1] = amd64_merge_classes (theclass[1], subclass[0]);
-         if (pos == 0)
-           theclass[1] = amd64_merge_classes (theclass[1], subclass[1]);
-       }
+      for (i = 0; i < type->num_fields (); i++)
+       amd64_classify_aggregate_field (type, i, theclass, 0);
     }
 
   /* 4. Then a post merger cleanup is done:  */
@@ -661,7 +708,7 @@ amd64_classify_aggregate (struct type *type, enum amd64_reg_class theclass[2])
 static void
 amd64_classify (struct type *type, enum amd64_reg_class theclass[2])
 {
-  enum type_code code = TYPE_CODE (type);
+  enum type_code code = type->code ();
   int len = TYPE_LENGTH (type);
 
   theclass[0] = theclass[1] = AMD64_NO_CLASS;
@@ -673,7 +720,7 @@ amd64_classify (struct type *type, enum amd64_reg_class theclass[2])
   if ((code == TYPE_CODE_INT || code == TYPE_CODE_ENUM
        || code == TYPE_CODE_BOOL || code == TYPE_CODE_RANGE
        || code == TYPE_CODE_CHAR
-       || code == TYPE_CODE_PTR || code == TYPE_CODE_REF)
+       || code == TYPE_CODE_PTR || TYPE_IS_REFERENCE (type))
       && (len == 1 || len == 2 || len == 4 || len == 8))
     theclass[0] = AMD64_INTEGER;
 
@@ -771,15 +818,15 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
     {
       if (readbuf)
        {
-         regcache_raw_read (regcache, AMD64_ST0_REGNUM, readbuf);
-         regcache_raw_read (regcache, AMD64_ST1_REGNUM, readbuf + 16);
+         regcache->raw_read (AMD64_ST0_REGNUM, readbuf);
+         regcache->raw_read (AMD64_ST1_REGNUM, readbuf + 16);
        }
 
       if (writebuf)
        {
          i387_return_value (gdbarch, regcache);
-         regcache_raw_write (regcache, AMD64_ST0_REGNUM, writebuf);
-         regcache_raw_write (regcache, AMD64_ST1_REGNUM, writebuf + 16);
+         regcache->raw_write (AMD64_ST0_REGNUM, writebuf);
+         regcache->raw_write (AMD64_ST1_REGNUM, writebuf + 16);
 
          /* Fix up the tag word such that both %st(0) and %st(1) are
             marked as valid.  */
@@ -846,11 +893,11 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
       gdb_assert (regnum != -1);
 
       if (readbuf)
-       regcache_raw_read_part (regcache, regnum, offset, min (len, 8),
-                               readbuf + i * 8);
+       regcache->raw_read_part (regnum, offset, std::min (len, 8),
+                                readbuf + i * 8);
       if (writebuf)
-       regcache_raw_write_part (regcache, regnum, offset, min (len, 8),
-                                writebuf + i * 8);
+       regcache->raw_write_part (regnum, offset, std::min (len, 8),
+                                 writebuf + i * 8);
     }
 
   return RETURN_VALUE_REGISTER_CONVENTION;
@@ -858,8 +905,8 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function,
 \f
 
 static CORE_ADDR
-amd64_push_arguments (struct regcache *regcache, int nargs,
-                     struct value **args, CORE_ADDR sp, int struct_return)
+amd64_push_arguments (struct regcache *regcache, int nargs, struct value **args,
+                     CORE_ADDR sp, function_call_return_method return_method)
 {
   static int integer_regnum[] =
   {
@@ -887,7 +934,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
   int i;
 
   /* Reserve a register for the "hidden" argument.  */
-  if (struct_return)
+if (return_method == return_method_struct)
     integer_reg++;
 
   for (i = 0; i < nargs; i++)
@@ -951,14 +998,17 @@ amd64_push_arguments (struct regcache *regcache, int nargs,
                  offset = 8;
                  break;
 
+               case AMD64_NO_CLASS:
+                 continue;
+
                default:
                  gdb_assert (!"Unexpected register class.");
                }
 
              gdb_assert (regnum != -1);
              memset (buf, 0, sizeof buf);
-             memcpy (buf, valbuf + j * 8, min (len, 8));
-             regcache_raw_write_part (regcache, regnum, offset, 8, buf);
+             memcpy (buf, valbuf + j * 8, std::min (len, 8));
+             regcache->raw_write_part (regnum, offset, 8, buf);
            }
        }
     }
@@ -993,19 +1043,27 @@ static CORE_ADDR
 amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
                       struct regcache *regcache, CORE_ADDR bp_addr,
                       int nargs, struct value **args,  CORE_ADDR sp,
-                      int struct_return, CORE_ADDR struct_addr)
+                      function_call_return_method return_method,
+                      CORE_ADDR struct_addr)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   gdb_byte buf[8];
 
+  /* BND registers can be in arbitrary values at the moment of the
+     inferior call.  This can cause boundary violations that are not
+     due to a real bug or even desired by the user.  The best to be done
+     is set the BND registers to allow access to the whole memory, INIT
+     state, before pushing the inferior call.   */
+  i387_reset_bnd_regs (gdbarch, regcache);
+
   /* Pass arguments.  */
-  sp = amd64_push_arguments (regcache, nargs, args, sp, struct_return);
+  sp = amd64_push_arguments (regcache, nargs, args, sp, return_method);
 
   /* Pass "hidden" argument".  */
-  if (struct_return)
+  if (return_method == return_method_struct)
     {
       store_unsigned_integer (buf, 8, byte_order, struct_addr);
-      regcache_cooked_write (regcache, AMD64_RDI_REGNUM, buf);
+      regcache->cooked_write (AMD64_RDI_REGNUM, buf);
     }
 
   /* Store return address.  */
@@ -1015,10 +1073,10 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 
   /* Finally, update the stack pointer...  */
   store_unsigned_integer (buf, 8, byte_order, sp);
-  regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+  regcache->cooked_write (AMD64_RSP_REGNUM, buf);
 
   /* ...and fake a frame pointer.  */
-  regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+  regcache->cooked_write (AMD64_RBP_REGNUM, buf);
 
   return sp + 16;
 }
@@ -1032,8 +1090,9 @@ struct amd64_insn
 {
   /* The number of opcode bytes.  */
   int opcode_len;
-  /* The offset of the rex prefix or -1 if not present.  */
-  int rex_offset;
+  /* The offset of the REX/VEX instruction encoding prefix or -1 if
+     not present.  */
+  int enc_prefix_offset;
   /* The offset to the first opcode byte.  */
   int opcode_offset;
   /* The offset to the modrm byte or -1 if not present.  */
@@ -1043,24 +1102,27 @@ struct amd64_insn
   gdb_byte *raw_insn;
 };
 
-struct displaced_step_closure
+struct amd64_displaced_step_copy_insn_closure : public displaced_step_copy_insn_closure
 {
+  amd64_displaced_step_copy_insn_closure (int insn_buf_len)
+  : insn_buf (insn_buf_len, 0)
+  {}
+
   /* For rip-relative insns, saved copy of the reg we use instead of %rip.  */
-  int tmp_used;
+  int tmp_used = 0;
   int tmp_regno;
   ULONGEST tmp_save;
 
   /* Details of the instruction.  */
   struct amd64_insn insn_details;
 
-  /* Amount of space allocated to insn_buf.  */
-  int max_len;
-
-  /* The possibly modified insn.
-     This is a variable-length field.  */
-  gdb_byte insn_buf[1];
+  /* The possibly modified insn.  */
+  gdb::byte_vector insn_buf;
 };
 
+typedef std::unique_ptr<amd64_displaced_step_copy_insn_closure>
+  amd64_displaced_step_copy_insn_closure_up;
+
 /* WARNING: Keep onebyte_has_modrm, twobyte_has_modrm in sync with
    ../opcodes/i386-dis.c (until libopcodes exports them, or an alternative,
    at which point delete these in favor of libopcodes' versions).  */
@@ -1119,6 +1181,22 @@ rex_prefix_p (gdb_byte pfx)
   return REX_PREFIX_P (pfx);
 }
 
+/* True if PFX is the start of the 2-byte VEX prefix.  */
+
+static bool
+vex2_prefix_p (gdb_byte pfx)
+{
+  return pfx == 0xc5;
+}
+
+/* True if PFX is the start of the 3-byte VEX prefix.  */
+
+static bool
+vex3_prefix_p (gdb_byte pfx)
+{
+  return pfx == 0xc4;
+}
+
 /* Skip the legacy instruction prefixes in INSN.
    We assume INSN is properly sentineled so we don't have to worry
    about falling off the end of the buffer.  */
@@ -1237,19 +1315,30 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
   details->raw_insn = insn;
 
   details->opcode_len = -1;
-  details->rex_offset = -1;
+  details->enc_prefix_offset = -1;
   details->opcode_offset = -1;
   details->modrm_offset = -1;
 
   /* Skip legacy instruction prefixes.  */
   insn = amd64_skip_prefixes (insn);
 
-  /* Skip REX instruction prefix.  */
+  /* Skip REX/VEX instruction encoding prefixes.  */
   if (rex_prefix_p (*insn))
     {
-      details->rex_offset = insn - start;
+      details->enc_prefix_offset = insn - start;
       ++insn;
     }
+  else if (vex2_prefix_p (*insn))
+    {
+      /* Don't record the offset in this case because this prefix has
+        no REX.B equivalent.  */
+      insn += 2;
+    }
+  else if (vex3_prefix_p (*insn))
+    {
+      details->enc_prefix_offset = insn - start;
+      insn += 3;
+    }
 
   details->opcode_offset = insn - start;
 
@@ -1299,7 +1388,7 @@ amd64_get_insn_details (gdb_byte *insn, struct amd64_insn *details)
    We set base = pc + insn_length so we can leave disp unchanged.  */
 
 static void
-fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
+fixup_riprel (struct gdbarch *gdbarch, amd64_displaced_step_copy_insn_closure *dsc,
              CORE_ADDR from, CORE_ADDR to, struct regcache *regs)
 {
   const struct amd64_insn *insn_details = &dsc->insn_details;
@@ -1314,8 +1403,8 @@ fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
   ++insn;
 
   /* Compute the rip-relative address. */
-  insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf,
-                                         dsc->max_len, from);
+  insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf.data (),
+                                         dsc->insn_buf.size (), from);
   rip_base = from + insn_length;
 
   /* We need a register to hold the address.
@@ -1324,10 +1413,22 @@ fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
   arch_tmp_regno = amd64_get_unused_input_int_reg (insn_details);
   tmp_regno = amd64_arch_reg_to_regnum (arch_tmp_regno);
 
-  /* REX.B should be unset as we were using rip-relative addressing,
-     but ensure it's unset anyway, tmp_regno is not r8-r15.  */
-  if (insn_details->rex_offset != -1)
-    dsc->insn_buf[insn_details->rex_offset] &= ~REX_B;
+  /* Position of the not-B bit in the 3-byte VEX prefix (in byte 1).  */
+  static constexpr gdb_byte VEX3_NOT_B = 0x20;
+
+  /* REX.B should be unset (VEX.!B set) as we were using rip-relative
+     addressing, but ensure it's unset (set for VEX) anyway, tmp_regno
+     is not r8-r15.  */
+  if (insn_details->enc_prefix_offset != -1)
+    {
+      gdb_byte *pfx = &dsc->insn_buf[insn_details->enc_prefix_offset];
+      if (rex_prefix_p (pfx[0]))
+       pfx[0] &= ~REX_B;
+      else if (vex3_prefix_p (pfx[0]))
+       pfx[1] |= VEX3_NOT_B;
+      else
+       gdb_assert_not_reached ("unhandled prefix");
+    }
 
   regcache_cooked_read_unsigned (regs, tmp_regno, &orig_value);
   dsc->tmp_regno = tmp_regno;
@@ -1349,7 +1450,7 @@ fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc,
 
 static void
 fixup_displaced_copy (struct gdbarch *gdbarch,
-                     struct displaced_step_closure *dsc,
+                     amd64_displaced_step_copy_insn_closure *dsc,
                      CORE_ADDR from, CORE_ADDR to, struct regcache *regs)
 {
   const struct amd64_insn *details = &dsc->insn_details;
@@ -1367,7 +1468,7 @@ fixup_displaced_copy (struct gdbarch *gdbarch,
     }
 }
 
-struct displaced_step_closure *
+displaced_step_copy_insn_closure_up
 amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
                                CORE_ADDR from, CORE_ADDR to,
                                struct regcache *regs)
@@ -1376,15 +1477,11 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
   /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
      continually watch for running off the end of the buffer.  */
   int fixup_sentinel_space = len;
-  struct displaced_step_closure *dsc
-    = ((struct displaced_step_closure *)
-       xmalloc (sizeof (*dsc) + len + fixup_sentinel_space));
+  std::unique_ptr<amd64_displaced_step_copy_insn_closure> dsc
+    (new amd64_displaced_step_copy_insn_closure (len + fixup_sentinel_space));
   gdb_byte *buf = &dsc->insn_buf[0];
   struct amd64_insn *details = &dsc->insn_details;
 
-  dsc->tmp_used = 0;
-  dsc->max_len = len + fixup_sentinel_space;
-
   read_memory (from, buf, len);
 
   /* Set up the sentinel space so we don't have to worry about running
@@ -1406,7 +1503,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
 
   /* Modify the insn to cope with the address where it will be executed from.
      In particular, handle any rip-relative addressing.         */
-  fixup_displaced_copy (gdbarch, dsc, from, to, regs);
+  fixup_displaced_copy (gdbarch, dsc.get (), from, to, regs);
 
   write_memory (to, buf, len);
 
@@ -1417,7 +1514,8 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
       displaced_step_dump_bytes (gdb_stdlog, buf, len);
     }
 
-  return dsc;
+  /* This is a work around for a problem with g++ 4.8.  */
+  return displaced_step_copy_insn_closure_up (dsc.release ());
 }
 
 static int
@@ -1579,14 +1677,15 @@ amd64_insn_is_jump (struct gdbarch *gdbarch, CORE_ADDR addr)
 
 void
 amd64_displaced_step_fixup (struct gdbarch *gdbarch,
-                           struct displaced_step_closure *dsc,
+                           struct displaced_step_copy_insn_closure *dsc_,
                            CORE_ADDR from, CORE_ADDR to,
                            struct regcache *regs)
 {
+  amd64_displaced_step_copy_insn_closure *dsc = (amd64_displaced_step_copy_insn_closure *) dsc_;
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   /* The offset we applied to the instruction's address.  */
   ULONGEST insn_offset = to - from;
-  gdb_byte *insn = dsc->insn_buf;
+  gdb_byte *insn = dsc->insn_buf.data ();
   const struct amd64_insn *insn_details = &dsc->insn_details;
 
   if (debug_displaced)
@@ -1764,15 +1863,47 @@ amd64_relocate_instruction (struct gdbarch *gdbarch,
      the user program would return to.  */
   if (insn[0] == 0xe8)
     {
-      gdb_byte push_buf[16];
-      unsigned int ret_addr;
+      gdb_byte push_buf[32];
+      CORE_ADDR ret_addr;
+      int i = 0;
 
       /* Where "ret" in the original code will return to.  */
       ret_addr = oldloc + insn_length;
-      push_buf[0] = 0x68; /* pushq $...  */
-      store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
+
+      /* If pushing an address higher than or equal to 0x80000000,
+        avoid 'pushq', as that sign extends its 32-bit operand, which
+        would be incorrect.  */
+      if (ret_addr <= 0x7fffffff)
+       {
+         push_buf[0] = 0x68; /* pushq $...  */
+         store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr);
+         i = 5;
+       }
+      else
+       {
+         push_buf[i++] = 0x48; /* sub    $0x8,%rsp */
+         push_buf[i++] = 0x83;
+         push_buf[i++] = 0xec;
+         push_buf[i++] = 0x08;
+
+         push_buf[i++] = 0xc7; /* movl    $imm,(%rsp) */
+         push_buf[i++] = 0x04;
+         push_buf[i++] = 0x24;
+         store_unsigned_integer (&push_buf[i], 4, byte_order,
+                                 ret_addr & 0xffffffff);
+         i += 4;
+
+         push_buf[i++] = 0xc7; /* movl    $imm,4(%rsp) */
+         push_buf[i++] = 0x44;
+         push_buf[i++] = 0x24;
+         push_buf[i++] = 0x04;
+         store_unsigned_integer (&push_buf[i], 4, byte_order,
+                                 ret_addr >> 32);
+         i += 4;
+       }
+      gdb_assert (i <= sizeof (push_buf));
       /* Push the push.  */
-      append_insns (to, 5, push_buf);
+      append_insns (to, i, push_buf);
 
       /* Convert the relative call to a relative jump.  */
       insn[0] = 0xe9;
@@ -2035,7 +2166,7 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc > pc + offset_and)
     cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
 
-  return min (pc + offset + 2, current_pc);
+  return std::min (pc + offset + 2, current_pc);
 }
 
 /* Similar to amd64_analyze_stack_align for x32.  */
@@ -2217,7 +2348,7 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
   if (current_pc > pc + offset_and)
     cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
 
-  return min (pc + offset + 2, current_pc);
+  return std::min (pc + offset + 2, current_pc);
 }
 
 /* Do a limited analysis of the prologue at PC and update CACHE
@@ -2234,6 +2365,9 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
       pushq %rbp        0x55
       movl %esp, %ebp   0x89 0xe5 (or 0x8b 0xec)
 
+   The `endbr64` instruction can be found before these sequences, and will be
+   skipped if found.
+
    Any function that doesn't start with one of these sequences will be
    assumed to have no prologue and thus no valid frame pointer in
    %rbp.  */
@@ -2244,6 +2378,8 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
                        struct amd64_frame_cache *cache)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  /* The `endbr64` instruction.  */
+  static const gdb_byte endbr64[4] = { 0xf3, 0x0f, 0x1e, 0xfa };
   /* There are two variations of movq %rsp, %rbp.  */
   static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
   static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
@@ -2264,6 +2400,20 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
 
   op = read_code_unsigned_integer (pc, 1, byte_order);
 
+  /* Check for the `endbr64` instruction, skip it if found.  */
+  if (op == endbr64[0])
+    {
+      read_code (pc + 1, buf, 3);
+
+      if (memcmp (buf, &endbr64[1], 3) == 0)
+       pc += 4;
+
+      op = read_code_unsigned_integer (pc, 1, byte_order);
+    }
+
+  if (current_pc <= pc)
+    return current_pc;
+
   if (op == 0x55)              /* pushq %rbp */
     {
       /* Take into account that we've executed the `pushq %rbp' that
@@ -2406,7 +2556,7 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
          && (cust != NULL
              && COMPUNIT_PRODUCER (cust) != NULL
              && startswith (COMPUNIT_PRODUCER (cust), "clang ")))
-        return max (start_pc, post_prologue_pc);
+        return std::max (start_pc, post_prologue_pc);
     }
 
   amd64_init_frame_cache (&cache);
@@ -2501,16 +2651,15 @@ amd64_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache = amd64_alloc_frame_cache ();
   *this_cache = cache;
 
-  TRY
+  try
     {
       amd64_frame_cache_1 (this_frame, cache);
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
     }
-  END_CATCH
 
   return cache;
 }
@@ -2619,7 +2768,7 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
 
   cache = amd64_alloc_frame_cache ();
 
-  TRY
+  try
     {
       get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
       cache->base = extract_unsigned_integer (buf, 8, byte_order) - 8;
@@ -2633,12 +2782,11 @@ amd64_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       cache->base_p = 1;
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
     }
-  END_CATCH
 
   *this_cache = cache;
   return cache;
@@ -2796,7 +2944,7 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
   cache = amd64_alloc_frame_cache ();
   *this_cache = cache;
 
-  TRY
+  try
     {
       /* Cache base will be %esp plus cache->sp_offset (-8).  */
       get_frame_register (this_frame, AMD64_RSP_REGNUM, buf);
@@ -2814,12 +2962,11 @@ amd64_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache)
 
       cache->base_p = 1;
     }
-  CATCH (ex, RETURN_MASK_ERROR)
+  catch (const gdb_exception_error &ex)
     {
       if (ex.error != NOT_AVAILABLE_ERROR)
-       throw_exception (ex);
+       throw;
     }
-  END_CATCH
 
   return cache;
 }
@@ -2888,7 +3035,7 @@ static void
 amd64_supply_fpregset (const struct regset *regset, struct regcache *regcache,
                       int regnum, const void *fpregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   gdb_assert (len >= tdep->sizeof_fpregset);
@@ -2905,7 +3052,7 @@ amd64_collect_fpregset (const struct regset *regset,
                        const struct regcache *regcache,
                        int regnum, void *fpregs, size_t len)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   const struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   gdb_assert (len >= tdep->sizeof_fpregset);
@@ -2959,8 +3106,19 @@ static const int amd64_record_regmap[] =
   AMD64_DS_REGNUM, AMD64_ES_REGNUM, AMD64_FS_REGNUM, AMD64_GS_REGNUM
 };
 
+/* Implement the "in_indirect_branch_thunk" gdbarch function.  */
+
+static bool
+amd64_in_indirect_branch_thunk (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  return x86_in_indirect_branch_thunk (pc, amd64_register_names,
+                                      AMD64_RAX_REGNUM,
+                                      AMD64_RIP_REGNUM);
+}
+
 void
-amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
+               const target_desc *default_tdesc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct target_desc *tdesc = info.target_desc;
@@ -2977,7 +3135,7 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   tdep->fpregset = &amd64_fpregset;
 
   if (! tdesc_has_registers (tdesc))
-    tdesc = tdesc_amd64;
+    tdesc = default_tdesc;
   tdep->tdesc = tdesc;
 
   tdep->num_core_regs = AMD64_NUM_GREGS + I387_NUM_REGS;
@@ -3014,6 +3172,18 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
       tdep->bnd0r_regnum = AMD64_BND0R_REGNUM;
     }
 
+  if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL)
+    {
+      tdep->fsbase_regnum = AMD64_FSBASE_REGNUM;
+    }
+
+  if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys") != NULL)
+    {
+      tdep->pkeys_register_names = amd64_pkeys_names;
+      tdep->pkru_regnum = AMD64_PKRU_REGNUM;
+      tdep->num_pkeys_regs = 1;
+    }
+
   tdep->num_byte_regs = 20;
   tdep->num_word_regs = 16;
   tdep->num_dword_regs = 16;
@@ -3110,8 +3280,19 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_insn_is_call (gdbarch, amd64_insn_is_call);
   set_gdbarch_insn_is_ret (gdbarch, amd64_insn_is_ret);
   set_gdbarch_insn_is_jump (gdbarch, amd64_insn_is_jump);
+
+  set_gdbarch_in_indirect_branch_thunk (gdbarch,
+                                       amd64_in_indirect_branch_thunk);
+}
+
+/* Initialize ARCH for x86-64, no osabi.  */
+
+static void
+amd64_none_init_abi (gdbarch_info info, gdbarch *arch)
+{
+  amd64_init_abi (info, arch, amd64_target_description (X86_XSTATE_SSE_MASK,
+                                                       true));
 }
-\f
 
 static struct type *
 amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
@@ -3131,16 +3312,12 @@ amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
 }
 
 void
-amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch,
+                   const target_desc *default_tdesc)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-  const struct target_desc *tdesc = info.target_desc;
 
-  amd64_init_abi (info, gdbarch);
-
-  if (! tdesc_has_registers (tdesc))
-    tdesc = tdesc_x32;
-  tdep->tdesc = tdesc;
+  amd64_init_abi (info, gdbarch, default_tdesc);
 
   tdep->num_dword_regs = 17;
   set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
@@ -3149,42 +3326,45 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_ptr_bit (gdbarch, 32);
 }
 
+/* Initialize ARCH for x64-32, no osabi.  */
+
+static void
+amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
+{
+  amd64_x32_init_abi (info, arch,
+                     amd64_target_description (X86_XSTATE_SSE_MASK, true));
+}
+
 /* Return the target description for a specified XSAVE feature mask.  */
 
 const struct target_desc *
-amd64_target_description (uint64_t xcr0)
-{
-  switch (xcr0 & X86_XSTATE_ALL_MASK)
-    {
-    case X86_XSTATE_MPX_AVX512_MASK:
-    case X86_XSTATE_AVX512_MASK:
-      return tdesc_amd64_avx512;
-    case X86_XSTATE_MPX_MASK:
-      return tdesc_amd64_mpx;
-    case X86_XSTATE_AVX_MPX_MASK:
-      return tdesc_amd64_avx_mpx;
-    case X86_XSTATE_AVX_MASK:
-      return tdesc_amd64_avx;
-    default:
-      return tdesc_amd64;
-    }
-}
+amd64_target_description (uint64_t xcr0, bool segments)
+{
+  static target_desc *amd64_tdescs \
+    [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
+  target_desc **tdesc;
+
+  tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
+    [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+    [segments ? 1 : 0];
+
+  if (*tdesc == NULL)
+    *tdesc = amd64_create_target_description (xcr0, false, false,
+                                             segments);
 
-/* Provide a prototype to silence -Wmissing-prototypes.  */
-void _initialize_amd64_tdep (void);
+  return *tdesc;
+}
 
+void _initialize_amd64_tdep ();
 void
-_initialize_amd64_tdep (void)
+_initialize_amd64_tdep ()
 {
-  initialize_tdesc_amd64 ();
-  initialize_tdesc_amd64_avx ();
-  initialize_tdesc_amd64_mpx ();
-  initialize_tdesc_amd64_avx_mpx ();
-  initialize_tdesc_amd64_avx512 ();
-
-  initialize_tdesc_x32 ();
-  initialize_tdesc_x32_avx ();
-  initialize_tdesc_x32_avx512 ();
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x86_64, GDB_OSABI_NONE,
+                         amd64_none_init_abi);
+  gdbarch_register_osabi (bfd_arch_i386, bfd_mach_x64_32, GDB_OSABI_NONE,
+                         amd64_x32_none_init_abi);
 }
 \f
 
@@ -3204,7 +3384,7 @@ void
 amd64_supply_fxsave (struct regcache *regcache, int regnum,
                     const void *fxsave)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   i387_supply_fxsave (regcache, regnum, fxsave);
@@ -3215,9 +3395,9 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum,
       const gdb_byte *regs = (const gdb_byte *) fxsave;
 
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
-       regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
+       regcache->raw_supply (I387_FISEG_REGNUM (tdep), regs + 12);
       if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
-       regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep), regs + 20);
+       regcache->raw_supply (I387_FOSEG_REGNUM (tdep), regs + 20);
     }
 }
 
@@ -3227,7 +3407,7 @@ void
 amd64_supply_xsave (struct regcache *regcache, int regnum,
                    const void *xsave)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   i387_supply_xsave (regcache, regnum, xsave);
@@ -3236,13 +3416,20 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
       && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       const gdb_byte *regs = (const gdb_byte *) xsave;
+      ULONGEST clear_bv;
 
-      if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
-       regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep),
-                            regs + 12);
-      if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
-       regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep),
-                            regs + 20);
+      clear_bv = i387_xsave_get_clear_bv (gdbarch, xsave);
+
+      /* If the FISEG and FOSEG registers have not been initialised yet
+        (their CLEAR_BV bit is set) then their default values of zero will
+        have already been setup by I387_SUPPLY_XSAVE.  */
+      if (!(clear_bv & X86_XSTATE_X87))
+       {
+         if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
+           regcache->raw_supply (I387_FISEG_REGNUM (tdep), regs + 12);
+         if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
+           regcache->raw_supply (I387_FOSEG_REGNUM (tdep), regs + 20);
+       }
     }
 }
 
@@ -3255,7 +3442,7 @@ void
 amd64_collect_fxsave (const struct regcache *regcache, int regnum,
                      void *fxsave)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   gdb_byte *regs = (gdb_byte *) fxsave;
 
@@ -3264,9 +3451,9 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum,
   if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
-       regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
+       regcache->raw_collect (I387_FISEG_REGNUM (tdep), regs + 12);
       if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
-       regcache_raw_collect (regcache, I387_FOSEG_REGNUM (tdep), regs + 20);
+       regcache->raw_collect (I387_FOSEG_REGNUM (tdep), regs + 20);
     }
 }
 
@@ -3276,7 +3463,7 @@ void
 amd64_collect_xsave (const struct regcache *regcache, int regnum,
                     void *xsave, int gcore)
 {
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   gdb_byte *regs = (gdb_byte *) xsave;
 
@@ -3285,10 +3472,10 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum,
   if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
     {
       if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
-       regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),
+       regcache->raw_collect (I387_FISEG_REGNUM (tdep),
                              regs + 12);
       if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
-       regcache_raw_collect (regcache, I387_FOSEG_REGNUM (tdep),
+       regcache->raw_collect (I387_FOSEG_REGNUM (tdep),
                              regs + 20);
     }
 }
This page took 0.040044 seconds and 4 git commands to generate.