X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fi387-tdep.c;h=574914cab78f6b62a720a08e6a70de5b171d92ef;hb=6a2c1b8790e58ce0688507b5b1f8369aa621a665;hp=d66ac6ab07941ba0922f2122ec014feeec5dd4c2;hpb=df7e526582809b829ee8651a1315a17627cfea4d;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index d66ac6ab07..574914cab7 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -1,6 +1,6 @@ /* Intel 387 floating point stuff. - Copyright (C) 1988-2014 Free Software Foundation, Inc. + Copyright (C) 1988-2017 Free Software Foundation, Inc. This file is part of GDB. @@ -341,8 +341,9 @@ i387_convert_register_p (struct gdbarch *gdbarch, int regnum, if (i386_fp_regnum_p (gdbarch, regnum)) { /* Floating point registers must be converted unless we are - accessing them in their hardware type. */ - if (type == i387_ext_type (gdbarch)) + accessing them in their hardware type or TYPE is not float. */ + if (type == i387_ext_type (gdbarch) + || TYPE_CODE (type) != TYPE_CODE_FLT) return 0; else return 1; @@ -374,7 +375,8 @@ i387_register_to_value (struct frame_info *frame, int regnum, } /* Convert to TYPE. */ - if (!get_frame_register_bytes (frame, regnum, 0, TYPE_LENGTH (type), + if (!get_frame_register_bytes (frame, regnum, 0, + register_size (gdbarch, regnum), from, optimizedp, unavailablep)) return 0; @@ -449,7 +451,7 @@ i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave) struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - const gdb_byte *regs = fsave; + const gdb_byte *regs = (const gdb_byte *) fsave; int i; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -502,7 +504,7 @@ void i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave) { struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache)); - gdb_byte *regs = fsave; + gdb_byte *regs = (gdb_byte *) fsave; int i; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -595,7 +597,7 @@ void i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave) { struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache)); - const gdb_byte *regs = fxsave; + const gdb_byte *regs = (const gdb_byte *) fxsave; int i; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -678,7 +680,7 @@ void i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave) { struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache)); - gdb_byte *regs = fxsave; + gdb_byte *regs = (gdb_byte *) fxsave; int i; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -888,6 +890,19 @@ static int xsave_avx512_zmm_h_offset[] = #define XSAVE_AVX512_ZMM_H_ADDR(tdep, xsave, regnum) \ (xsave + xsave_avx512_zmm_h_offset[regnum - I387_ZMM0H_REGNUM (tdep)]) +/* At xsave_pkeys_offset[REGNUM] you find the offset to the location + of the PKRU register data structure used by the "xsave" + instruction where GDB register REGNUM is stored. */ + +static int xsave_pkeys_offset[] = +{ +2688 + 0 * 8 /* %pkru (64 bits in XSTATE, 32-bit actually used by + instructions and applications). */ +}; + +#define XSAVE_PKEYS_ADDR(tdep, xsave, regnum) \ + (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)]) + /* Similar to i387_supply_fxsave, but use XSAVE extended state. */ void @@ -896,10 +911,10 @@ i387_supply_xsave (struct regcache *regcache, int regnum, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - const gdb_byte *regs = xsave; + const gdb_byte *regs = (const gdb_byte *) xsave; int i; - unsigned int clear_bv; - static const gdb_byte zero[MAX_REGISTER_SIZE] = { 0 }; + ULONGEST clear_bv; + static const gdb_byte zero[I386_MAX_REGISTER_SIZE] = { 0 }; enum { none = 0x0, @@ -911,8 +926,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, avx512_zmm_h = 0x20, avx512_ymmh_avx512 = 0x40, avx512_xmm_avx512 = 0x80, + pkeys = 0x100, all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h - | avx512_ymmh_avx512 | avx512_xmm_avx512 + | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys } regclass; gdb_assert (regs != NULL); @@ -921,6 +937,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if (regnum == -1) regclass = all; + else if (regnum >= I387_PKRU_REGNUM (tdep) + && regnum < I387_PKEYSEND_REGNUM (tdep)) + regclass = pkeys; else if (regnum >= I387_ZMM0H_REGNUM (tdep) && regnum < I387_ZMMENDH_REGNUM (tdep)) regclass = avx512_zmm_h; @@ -950,12 +969,15 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if (regclass != none) { - /* Get `xstat_bv'. */ - const gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs); + /* Get `xstat_bv'. The supported bits in `xstat_bv' are 8 bytes. */ + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + ULONGEST xstate_bv = 0; - /* The supported bits in `xstat_bv' are 1 byte. Clear part in - vector registers if its bit in xstat_bv is zero. */ - clear_bv = (~(*xstate_bv_p)) & tdep->xcr0; + xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs), + 8, byte_order); + + /* Clear part in vector registers if its bit in xstat_bv is zero. */ + clear_bv = (~(xstate_bv)) & tdep->xcr0; } else clear_bv = X86_XSTATE_ALL_MASK; @@ -974,6 +996,14 @@ i387_supply_xsave (struct regcache *regcache, int regnum, case none: break; + case pkeys: + if ((clear_bv & X86_XSTATE_PKRU)) + regcache_raw_supply (regcache, regnum, zero); + else + regcache_raw_supply (regcache, regnum, + XSAVE_PKEYS_ADDR (tdep, regs, regnum)); + return; + case avx512_zmm_h: if ((clear_bv & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) regcache_raw_supply (regcache, regnum, zero); @@ -1039,6 +1069,26 @@ i387_supply_xsave (struct regcache *regcache, int regnum, return; case all: + /* Handle PKEYS registers. */ + if ((tdep->xcr0 & X86_XSTATE_PKRU)) + { + if ((clear_bv & X86_XSTATE_PKRU)) + { + for (i = I387_PKRU_REGNUM (tdep); + i < I387_PKEYSEND_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, zero); + } + else + { + for (i = I387_PKRU_REGNUM (tdep); + i < I387_PKEYSEND_REGNUM (tdep); + i++) + regcache_raw_supply (regcache, i, + XSAVE_PKEYS_ADDR (tdep, regs, i)); + } + } + /* Handle the upper ZMM registers. */ if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) { @@ -1269,7 +1319,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, { struct gdbarch *gdbarch = get_regcache_arch (regcache); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - gdb_byte *regs = xsave; + gdb_byte *regs = (gdb_byte *) xsave; int i; enum { @@ -1283,8 +1333,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, avx512_zmm_h = 0x40 | check, avx512_ymmh_avx512 = 0x80 | check, avx512_xmm_avx512 = 0x100 | check, + pkeys = 0x200 | check, all = x87 | sse | avxh | mpx | avx512_k | avx512_zmm_h - | avx512_ymmh_avx512 | avx512_xmm_avx512 + | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys } regclass; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -1292,6 +1343,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (regnum == -1) regclass = all; + else if (regnum >= I387_PKRU_REGNUM (tdep) + && regnum < I387_PKEYSEND_REGNUM (tdep)) + regclass = pkeys; else if (regnum >= I387_ZMM0H_REGNUM (tdep) && regnum < I387_ZMMENDH_REGNUM (tdep)) regclass = avx512_zmm_h; @@ -1333,15 +1387,23 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if ((regclass & check)) { gdb_byte raw[I386_MAX_REGISTER_SIZE]; - gdb_byte *xstate_bv_p = XSAVE_XSTATE_BV_ADDR (regs); - unsigned int xstate_bv = 0; - /* The supported bits in `xstat_bv' are 1 byte. */ - unsigned int clear_bv = (~(*xstate_bv_p)) & tdep->xcr0; + ULONGEST initial_xstate_bv, clear_bv, xstate_bv = 0; gdb_byte *p; + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + /* The supported bits in `xstat_bv' are 8 bytes. */ + initial_xstate_bv = extract_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs), + 8, byte_order); + clear_bv = (~(initial_xstate_bv)) & tdep->xcr0; /* Clear register set if its bit in xstat_bv is zero. */ if (clear_bv) { + if ((clear_bv & X86_XSTATE_PKRU)) + for (i = I387_PKRU_REGNUM (tdep); + i < I387_PKEYSEND_REGNUM (tdep); i++) + memset (XSAVE_PKEYS_ADDR (tdep, regs, i), 0, 4); + if ((clear_bv & X86_XSTATE_BNDREGS)) for (i = I387_BND0R_REGNUM (tdep); i < I387_BNDCFGU_REGNUM (tdep); i++) @@ -1390,6 +1452,20 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (regclass == all) { + /* Check if any PKEYS registers are changed. */ + if ((tdep->xcr0 & X86_XSTATE_PKRU)) + for (i = I387_PKRU_REGNUM (tdep); + i < I387_PKEYSEND_REGNUM (tdep); i++) + { + regcache_raw_collect (regcache, i, raw); + p = XSAVE_PKEYS_ADDR (tdep, regs, i); + if (memcmp (raw, p, 4) != 0) + { + xstate_bv |= X86_XSTATE_PKRU; + memcpy (p, raw, 4); + } + } + /* Check if any ZMMH registers are changed. */ if ((tdep->xcr0 & (X86_XSTATE_ZMM_H | X86_XSTATE_ZMM))) for (i = I387_ZMM0H_REGNUM (tdep); @@ -1525,6 +1601,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, internal_error (__FILE__, __LINE__, _("invalid i387 regclass")); + case pkeys: + /* This is a PKEYS register. */ + p = XSAVE_PKEYS_ADDR (tdep, regs, regnum); + if (memcmp (raw, p, 4) != 0) + { + xstate_bv |= X86_XSTATE_PKRU; + memcpy (p, raw, 4); + } + break; + case avx512_zmm_h: /* This is a ZMM register. */ p = XSAVE_AVX512_ZMM_H_ADDR (tdep, regs, regnum); @@ -1619,8 +1705,11 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, registers are changed. */ if (xstate_bv) { - /* The supported bits in `xstat_bv' are 1 byte. */ - *xstate_bv_p |= (gdb_byte) xstate_bv; + /* The supported bits in `xstat_bv' are 8 bytes. */ + initial_xstate_bv |= xstate_bv; + store_unsigned_integer (XSAVE_XSTATE_BV_ADDR (regs), + 8, byte_order, + initial_xstate_bv); switch (regclass) { @@ -1639,6 +1728,7 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, case avx512_zmm_h: case avx512_ymmh_avx512: case avx512_xmm_avx512: + case pkeys: /* Register REGNUM has been updated. Return. */ return; } @@ -1772,3 +1862,20 @@ i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache) regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff); } + +/* See i387-tdep.h. */ + +void +i387_reset_bnd_regs (struct gdbarch *gdbarch, struct regcache *regcache) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (I387_BND0R_REGNUM (tdep) > 0) + { + gdb_byte bnd_buf[16]; + + memset (bnd_buf, 0, 16); + for (int i = 0; i < I387_NUM_BND_REGS; i++) + regcache_raw_write (regcache, I387_BND0R_REGNUM (tdep) + i, bnd_buf); + } +}