]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdbserver/i387-fp.cc
New Romanian translation for gas sub-directory
[thirdparty/binutils-gdb.git] / gdbserver / i387-fp.cc
index 12cb614e5d814e94956e32f7f02a20a3004d2bb5..60d565b84823d42ad4ef72abf2e9c175b5c83d5b 100644 (file)
@@ -1,5 +1,5 @@
 /* i387-specific utility functions, for the remote server for GDB.
-   Copyright (C) 2000-2023 Free Software Foundation, Inc.
+   Copyright (C) 2000-2024 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
 #include "server.h"
 #include "i387-fp.h"
 #include "gdbsupport/x86-xstate.h"
+#include "nat/x86-xstate.h"
+
+/* Default to SSE.  */
+static unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
 
 static const int num_mpx_bnd_registers = 4;
 static const int num_mpx_cfg_registers = 2;
 static const int num_avx512_k_registers = 8;
 static const int num_pkeys_registers = 1;
 
+static x86_xsave_layout xsave_layout;
+
 /* Note: These functions preserve the reserved bits in control registers.
    However, gdbserver promptly throws away that information.  */
 
 /* These structs should have the proper sizes and alignment on both
    i386 and x86-64 machines.  */
 
-struct i387_fsave {
+struct i387_fsave
+{
   /* All these are only sixteen bits, plus padding, except for fop (which
      is only eleven bits), and fooff / fioff (which are 32 bits each).  */
   unsigned short fctrl;
@@ -51,7 +58,8 @@ struct i387_fsave {
   unsigned char st_space[80];
 };
 
-struct i387_fxsave {
+struct i387_fxsave
+{
   /* All these are only sixteen bits, plus padding, except for fop (which
      is only eleven bits), and fooff / fioff (which are 32 bits each).  */
   unsigned short fctrl;
@@ -75,29 +83,10 @@ struct i387_fxsave {
   unsigned char xmm_space[256];
 };
 
-struct i387_xsave {
-  /* All these are only sixteen bits, plus padding, except for fop (which
-     is only eleven bits), and fooff / fioff (which are 32 bits each).  */
-  unsigned short fctrl;
-  unsigned short fstat;
-  unsigned short ftag;
-  unsigned short fop;
-  unsigned int fioff;
-  unsigned short fiseg;
-  unsigned short pad1;
-  unsigned int fooff;
-  unsigned short foseg;
-  unsigned short pad12;
-
-  unsigned int mxcsr;
-  unsigned int mxcsr_mask;
-
-  /* Space for eight 80-bit FP values in 128-bit spaces.  */
-  unsigned char st_space[128];
-
-  /* Space for eight 128-bit XMM values, or 16 on x86-64.  */
-  unsigned char xmm_space[256];
+static_assert (sizeof(i387_fxsave) == 416);
 
+struct i387_xsave : public i387_fxsave
+{
   unsigned char reserved1[48];
 
   /* The extended control register 0 (the XFEATURE_ENABLED_MASK
@@ -109,36 +98,57 @@ struct i387_xsave {
   /* The XSTATE_BV bit vector.  */
   unsigned long long xstate_bv;
 
-  unsigned char reserved3[56];
+  /* The XCOMP_BV bit vector.  */
+  unsigned long long xcomp_bv;
 
-  /* Space for eight upper 128-bit YMM values, or 16 on x86-64.  */
-  unsigned char ymmh_space[256];
+  unsigned char reserved3[48];
 
-  unsigned char reserved4[128];
+  /* Byte 576.  End of registers with fixed position in XSAVE.
+     The position of other XSAVE registers will be calculated
+     from the appropriate CPUID calls.  */
 
-  /* Space for 4 bound registers values of 128 bits.  */
-  unsigned char mpx_bnd_space[64];
-
-  /* Space for 2 MPX configuration registers of 64 bits
-     plus reserved space.  */
-  unsigned char mpx_cfg_space[16];
+private:
+  /* Base address of XSAVE data as an unsigned char *.  Used to derive
+     pointers to XSAVE state components in the extended state
+     area.  */
+  unsigned char *xsave ()
+  { return reinterpret_cast<unsigned char *> (this); }
 
-  unsigned char reserved5[48];
+public:
+  /* Memory address of eight upper 128-bit YMM values, or 16 on x86-64.  */
+  unsigned char *ymmh_space ()
+  { return xsave () + xsave_layout.avx_offset; }
 
-  /* Space for 8 OpMask register values of 64 bits.  */
-  unsigned char k_space[64];
+  /* Memory address of 4 bound registers values of 128 bits.  */
+  unsigned char *bndregs_space ()
+  { return xsave () + xsave_layout.bndregs_offset; }
 
-  /* Space for 16 256-bit zmm0-15.  */
-  unsigned char zmmh_low_space[512];
-
-  /* Space for 16 512-bit zmm16-31 values.  */
-  unsigned char zmmh_high_space[1024];
-
-  /* Space for 1 32-bit PKRU register.  The HW XSTATE size for this feature is
-     actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper 32 bits.  */
-  unsigned char pkru_space[8];
+  /* Memory address of 2 MPX configuration registers of 64 bits
+     plus reserved space.  */
+  unsigned char *bndcfg_space ()
+  { return xsave () + xsave_layout.bndcfg_offset; }
+
+  /* Memory address of 8 OpMask register values of 64 bits.  */
+  unsigned char *k_space ()
+  { return xsave () + xsave_layout.k_offset; }
+
+  /* Memory address of 16 256-bit zmm0-15.  */
+  unsigned char *zmmh_space ()
+  { return xsave () + xsave_layout.zmm_h_offset; }
+
+  /* Memory address of 16 512-bit zmm16-31 values.  */
+  unsigned char *zmm16_space ()
+  { return xsave () + xsave_layout.zmm_offset; }
+
+  /* Memory address of 1 32-bit PKRU register.  The HW XSTATE size for this
+     feature is actually 64 bits, but WRPKRU/RDPKRU instructions ignore upper
+     32 bits.  */
+  unsigned char *pkru_space ()
+  { return xsave () + xsave_layout.pkru_offset; }
 };
 
+static_assert (sizeof(i387_xsave) == 576);
+
 void
 i387_cache_to_fsave (struct regcache *regcache, void *buf)
 {
@@ -258,16 +268,12 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
   unsigned long long xstate_bv = 0;
   unsigned long long clear_bv = 0;
   char raw[64];
-  char *p;
+  unsigned char *p;
 
   /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
-  /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm.  */
-  int num_avx512_zmmh_low_registers = num_xmm_registers;
-  /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
-  int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
-  int num_avx512_ymmh_registers = amd64 ? 16 : 0;
-  int num_avx512_xmm_registers = amd64 ? 16 : 0;
+  /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
+  int num_zmm_high_registers = amd64 ? 16 : 0;
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
@@ -298,40 +304,34 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
 
       if ((clear_bv & X86_XSTATE_AVX))
        for (i = 0; i < num_xmm_registers; i++)
-         memset (((char *) &fp->ymmh_space[0]) + i * 16, 0, 16);
+         memset (fp->ymmh_space () + i * 16, 0, 16);
 
       if ((clear_bv & X86_XSTATE_SSE) && (clear_bv & X86_XSTATE_AVX))
        memset (((char *) &fp->mxcsr), 0, 4);
 
       if ((clear_bv & X86_XSTATE_BNDREGS))
        for (i = 0; i < num_mpx_bnd_registers; i++)
-         memset (((char *) &fp->mpx_bnd_space[0]) + i * 16, 0, 16);
+         memset (fp->bndregs_space () + i * 16, 0, 16);
 
       if ((clear_bv & X86_XSTATE_BNDCFG))
        for (i = 0; i < num_mpx_cfg_registers; i++)
-         memset (((char *) &fp->mpx_cfg_space[0]) + i * 8, 0, 8);
+         memset (fp->bndcfg_space () + i * 8, 0, 8);
 
       if ((clear_bv & X86_XSTATE_K))
        for (i = 0; i < num_avx512_k_registers; i++)
-         memset (((char *) &fp->k_space[0]) + i * 8, 0, 8);
+         memset (fp->k_space () + i * 8, 0, 8);
 
       if ((clear_bv & X86_XSTATE_ZMM_H))
-       for (i = 0; i < num_avx512_zmmh_low_registers; i++)
-         memset (((char *) &fp->zmmh_low_space[0]) + i * 32, 0, 32);
+       for (i = 0; i < num_xmm_registers; i++)
+         memset (fp->zmmh_space () + i * 32, 0, 32);
 
       if ((clear_bv & X86_XSTATE_ZMM))
-       {
-         for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-           memset (((char *) &fp->zmmh_low_space[0]) + 32 + i * 64, 0, 32);
-         for (i = 0; i < num_avx512_xmm_registers; i++)
-           memset (((char *) &fp->zmmh_high_space[0]) + i * 64, 0, 16);
-         for (i = 0; i < num_avx512_ymmh_registers; i++)
-           memset (((char *) &fp->zmmh_high_space[0]) + 16 + i * 64, 0, 16);
-       }
+       for (i = 0; i < num_zmm_high_registers; i++)
+         memset (fp->zmm16_space () + i * 64, 0, 64);
 
       if ((clear_bv & X86_XSTATE_PKRU))
        for (i = 0; i < num_pkeys_registers; i++)
-         memset (((char *) &fp->pkru_space[0]) + i * 4, 0, 4);
+         memset (fp->pkru_space () + i * 4, 0, 4);
     }
 
   /* Check if any x87 registers are changed.  */
@@ -342,7 +342,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < 8; i++)
        {
          collect_register (regcache, i + st0_regnum, raw);
-         p = ((char *) &fp->st_space[0]) + i * 16;
+         p = fp->st_space + i * 16;
          if (memcmp (raw, p, 10))
            {
              xstate_bv |= X86_XSTATE_X87;
@@ -359,7 +359,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_xmm_registers; i++) 
        {
          collect_register (regcache, i + xmm0_regnum, raw);
-         p = ((char *) &fp->xmm_space[0]) + i * 16;
+         p = fp->xmm_space + i * 16;
          if (memcmp (raw, p, 16))
            {
              xstate_bv |= X86_XSTATE_SSE;
@@ -376,7 +376,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_xmm_registers; i++) 
        {
          collect_register (regcache, i + ymm0h_regnum, raw);
-         p = ((char *) &fp->ymmh_space[0]) + i * 16;
+         p = fp->ymmh_space () + i * 16;
          if (memcmp (raw, p, 16))
            {
              xstate_bv |= X86_XSTATE_AVX;
@@ -393,7 +393,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_mpx_bnd_registers; i++)
        {
          collect_register (regcache, i + bnd0r_regnum, raw);
-         p = ((char *) &fp->mpx_bnd_space[0]) + i * 16;
+         p = fp->bndregs_space () + i * 16;
          if (memcmp (raw, p, 16))
            {
              xstate_bv |= X86_XSTATE_BNDREGS;
@@ -410,7 +410,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_mpx_cfg_registers; i++)
        {
          collect_register (regcache, i + bndcfg_regnum, raw);
-         p = ((char *) &fp->mpx_cfg_space[0]) + i * 8;
+         p = fp->bndcfg_space () + i * 8;
          if (memcmp (raw, p, 8))
            {
              xstate_bv |= X86_XSTATE_BNDCFG;
@@ -427,7 +427,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_avx512_k_registers; i++)
        {
          collect_register (regcache, i + k0_regnum, raw);
-         p = ((char *) &fp->k_space[0]) + i * 8;
+         p = fp->k_space () + i * 8;
          if (memcmp (raw, p, 8) != 0)
            {
              xstate_bv |= X86_XSTATE_K;
@@ -441,10 +441,10 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
     {
       int zmm0h_regnum = find_regno (regcache->tdesc, "zmm0h");
 
-      for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+      for (i = 0; i < num_xmm_registers; i++)
        {
          collect_register (regcache, i + zmm0h_regnum, raw);
-         p = ((char *) &fp->zmmh_low_space[0]) + i * 32;
+         p = fp->zmmh_space () + i * 32;
          if (memcmp (raw, p, 32) != 0)
            {
              xstate_bv |= X86_XSTATE_ZMM_H;
@@ -453,55 +453,35 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
        }
     }
 
-  /* Check if any of ZMM16H-ZMM31H registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
+  /* Check if any of ZMM16-ZMM31 registers are changed.  */
+  if ((x86_xcr0 & X86_XSTATE_ZMM) && num_zmm_high_registers != 0)
     {
-      int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
-                          ? -1
-                          : find_regno (regcache->tdesc, "zmm16h"));
+      int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
+      int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
+      int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
 
-      for (i = 0; i < num_avx512_zmmh_high_registers; i++)
+      for (i = 0; i < num_zmm_high_registers; i++)
        {
+         p = fp->zmm16_space () + i * 64;
+
+         /* ZMMH sub-register.  */
          collect_register (regcache, i + zmm16h_regnum, raw);
-         p = ((char *) &fp->zmmh_high_space[0]) + 32 + i * 64;
-         if (memcmp (raw, p, 32) != 0)
+         if (memcmp (raw, p + 32, 32) != 0)
            {
              xstate_bv |= X86_XSTATE_ZMM;
-             memcpy (p, raw, 32);
+             memcpy (p + 32, raw, 32);
            }
-       }
-    }
-
-  /* Check if any XMM_AVX512 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
-    {
-      int xmm_avx512_regnum = (num_avx512_xmm_registers == 0
-                              ? -1
-                              : find_regno (regcache->tdesc, "xmm16"));
 
-      for (i = 0; i < num_avx512_xmm_registers; i++)
-       {
-         collect_register (regcache, i + xmm_avx512_regnum, raw);
-         p = ((char *) &fp->zmmh_high_space[0]) + i * 64;
-         if (memcmp (raw, p, 16) != 0)
+         /* YMMH sub-register.  */
+         collect_register (regcache, i + ymm16h_regnum, raw);
+         if (memcmp (raw, p + 16, 16) != 0)
            {
              xstate_bv |= X86_XSTATE_ZMM;
-             memcpy (p, raw, 16);
+             memcpy (p + 16, raw, 16);
            }
-       }
-    }
-
-  /* Check if any YMMH_AVX512 registers are changed.  */
-  if ((x86_xcr0 & X86_XSTATE_ZMM))
-    {
-      int ymmh_avx512_regnum = (num_avx512_ymmh_registers == 0
-                               ? -1
-                               : find_regno (regcache->tdesc, "ymm16h"));
 
-      for (i = 0; i < num_avx512_ymmh_registers; i++)
-       {
-         collect_register (regcache, i + ymmh_avx512_regnum, raw);
-         p = ((char *) &fp->zmmh_high_space[0]) + 16 + i * 64;
+         /* XMM sub-register.  */
+         collect_register (regcache, i + xmm16_regnum, raw);
          if (memcmp (raw, p, 16) != 0)
            {
              xstate_bv |= X86_XSTATE_ZMM;
@@ -518,7 +498,7 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf)
       for (i = 0; i < num_pkeys_registers; i++)
        {
          collect_register (regcache, i + pkru_regnum, raw);
-         p = ((char *) &fp->pkru_space[0]) + i * 4;
+         p = fp->pkru_space () + i * 4;
          if (memcmp (raw, p, 4) != 0)
            {
              xstate_bv |= X86_XSTATE_PKRU;
@@ -719,21 +699,16 @@ void
 i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 {
   struct i387_xsave *fp = (struct i387_xsave *) buf;
-  struct i387_fxsave *fxp = (struct i387_fxsave *) buf;
   bool amd64 = register_size (regcache->tdesc, 0) == 8;
   int i, top;
   unsigned long val;
   unsigned long long clear_bv;
-  gdb_byte *p;
+  unsigned char *p;
 
    /* Amd64 has 16 xmm regs; I386 has 8 xmm regs.  */
   int num_xmm_registers = amd64 ? 16 : 8;
-  /* AVX512 extends the existing xmm/ymm registers to a wider mode: zmm.  */
-  int num_avx512_zmmh_low_registers = num_xmm_registers;
-  /* AVX512 adds 16 extra regs in Amd64 mode, but none in I386 mode.*/
-  int num_avx512_zmmh_high_registers = amd64 ? 16 : 0;
-  int num_avx512_ymmh_registers = amd64 ? 16 : 0;
-  int num_avx512_xmm_registers = amd64 ? 16 : 0;
+  /* AVX512 adds 16 extra ZMM regs in Amd64 mode, but none in I386 mode.*/
+  int num_zmm_high_registers = amd64 ? 16 : 0;
 
   /* The supported bits in `xstat_bv' are 8 bytes.  Clear part in
      vector registers if its bit in xstat_bv is zero.  */
@@ -785,7 +760,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
       else
        {
-         p = (gdb_byte *) &fp->ymmh_space[0];
+         p = fp->ymmh_space ();
          for (i = 0; i < num_xmm_registers; i++)
            supply_register (regcache, i + ymm0h_regnum, p + i * 16);
        }
@@ -803,7 +778,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
       else
        {
-         p = (gdb_byte *) &fp->mpx_bnd_space[0];
+         p = fp->bndregs_space ();
          for (i = 0; i < num_mpx_bnd_registers; i++)
            supply_register (regcache, i + bnd0r_regnum, p + i * 16);
        }
@@ -821,7 +796,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
       else
        {
-         p = (gdb_byte *) &fp->mpx_cfg_space[0];
+         p = fp->bndcfg_space ();
          for (i = 0; i < num_mpx_cfg_registers; i++)
            supply_register (regcache, i + bndcfg_regnum, p + i * 8);
        }
@@ -838,7 +813,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
       else
        {
-         p = (gdb_byte *) &fp->k_space[0];
+         p = fp->k_space ();
          for (i = 0; i < num_avx512_k_registers; i++)
            supply_register (regcache, i + k0_regnum, p + i * 8);
        }
@@ -850,47 +825,41 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
 
       if ((clear_bv & X86_XSTATE_ZMM_H) != 0)
        {
-         for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+         for (i = 0; i < num_xmm_registers; i++)
            supply_register_zeroed (regcache, i + zmm0h_regnum);
        }
       else
        {
-         p = (gdb_byte *) &fp->zmmh_low_space[0];
-         for (i = 0; i < num_avx512_zmmh_low_registers; i++)
+         p = fp->zmmh_space ();
+         for (i = 0; i < num_xmm_registers; i++)
            supply_register (regcache, i + zmm0h_regnum, p + i * 32);
        }
     }
 
-  if ((x86_xcr0 & X86_XSTATE_ZMM) != 0)
+  if ((x86_xcr0 & X86_XSTATE_ZMM) != 0 && num_zmm_high_registers != 0)
     {
-      int zmm16h_regnum = (num_avx512_zmmh_high_registers == 0
-                          ? -1
-                          : find_regno (regcache->tdesc, "zmm16h"));
-      int ymm16h_regnum = (num_avx512_ymmh_registers == 0
-                          ? -1
-                          : find_regno (regcache->tdesc, "ymm16h"));
-      int xmm16_regnum = (num_avx512_xmm_registers == 0
-                         ? -1
-                         : find_regno (regcache->tdesc, "xmm16"));
+      int zmm16h_regnum = find_regno (regcache->tdesc, "zmm16h");
+      int ymm16h_regnum = find_regno (regcache->tdesc, "ymm16h");
+      int xmm16_regnum = find_regno (regcache->tdesc, "xmm16");
 
       if ((clear_bv & X86_XSTATE_ZMM) != 0)
        {
-         for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-           supply_register_zeroed (regcache, i + zmm16h_regnum);
-         for (i = 0; i < num_avx512_ymmh_registers; i++)
-           supply_register_zeroed (regcache, i + ymm16h_regnum);
-         for (i = 0; i < num_avx512_xmm_registers; i++)
-           supply_register_zeroed (regcache, i + xmm16_regnum);
+         for (i = 0; i < num_zmm_high_registers; i++)
+           {
+             supply_register_zeroed (regcache, i + zmm16h_regnum);
+             supply_register_zeroed (regcache, i + ymm16h_regnum);
+             supply_register_zeroed (regcache, i + xmm16_regnum);
+           }
        }
       else
        {
-         p = (gdb_byte *) &fp->zmmh_high_space[0];
-         for (i = 0; i < num_avx512_zmmh_high_registers; i++)
-           supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
-         for (i = 0; i < num_avx512_ymmh_registers; i++)
-           supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
-         for (i = 0; i < num_avx512_xmm_registers; i++)
-           supply_register (regcache, i + xmm16_regnum, p + i * 64);
+         p = fp->zmm16_space ();
+         for (i = 0; i < num_zmm_high_registers; i++)
+           {
+             supply_register (regcache, i + zmm16h_regnum, p + 32 + i * 64);
+             supply_register (regcache, i + ymm16h_regnum, p + 16 + i * 64);
+             supply_register (regcache, i + xmm16_regnum, p + i * 64);
+           }
        }
     }
 
@@ -905,7 +874,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        }
       else
        {
-         p = (gdb_byte *) &fp->pkru_space[0];
+         p = fp->pkru_space ();
          for (i = 0; i < num_pkeys_registers; i++)
            supply_register (regcache, i + pkru_regnum, p + i * 4);
        }
@@ -956,7 +925,7 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
        {
          int tag;
          if (fp->ftag & (1 << i))
-           tag = i387_ftag (fxp, (i + 8 - top) % 8);
+           tag = i387_ftag (fp, (i + 8 - top) % 8);
          else
            tag = 3;
          val |= tag << (2 * i);
@@ -974,5 +943,11 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf)
     }
 }
 
-/* Default to SSE.  */
-unsigned long long x86_xcr0 = X86_XSTATE_SSE_MASK;
+/* See i387-fp.h.  */
+
+void
+i387_set_xsave_mask (uint64_t xcr0, int len)
+{
+  x86_xcr0 = xcr0;
+  xsave_layout = x86_fetch_xsave_layout (xcr0, len);
+}