libunwind-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libunwind-devel] add methods to access full xmm registers on i386


From: David Mosberger-Tang
Subject: Re: [Libunwind-devel] add methods to access full xmm registers on i386
Date: Tue, 11 Dec 2007 09:08:28 -0700

Looks like a good change to me.  Arun, if you're fine with it, I'll
check it in (send a "Signed-off-by:" if you don't mind).

Thanks,

  --david

On 12/11/07, Andrew Cagney <address@hidden> wrote:
> Hi,
>
> I noticed two possible limitations with the i386 interface:
>
> - unw_fpreg_t is defined as "long double"
>
> When remote unwinding, "long double" may not be what you think.  Since
> the type is used as a container, and not actually interpreted.  I've
> changed the type to a union vis:
> +typedef union {
> +  struct { uint8_t b[4]; } val32;
> +  struct { uint8_t b[10]; } val80;
> +  struct { uint8_t b[16]; } val128;
> +} unw_tdep_fpreg_t;
> from memory this was suggested a while back when the PPC was being
> discussed.
>
> - fetching the 128-bit xmm registers is a pain
>
> The interface, as defined, requires that they be fetched as lo/hi 64-bit
> halves.  With unw_fpreg_t enlarged to hold full 128-bit values, I can
> add full XMM registers to the enum list vis:
> +    UNW_X86_XMM0,      /* scratch */
> +    UNW_X86_XMM1,      /* scratch */
> ...
> (and hopefully tweaked every where where needed).  One thing to notice
> is that I've placed them after UNW_X86_CFA (so its value doesn't
> change), I suspect that, in future, these virtual registers should be
> given -ve values so that they can't get in the way of this register growth.
>
>
>
> I've appended true XMM enum definitions that, using the above, fetch the
> full registers.
>
> Andrew
>
>
> 2007-12-10  Andrew Cagney  <address@hidden>
>
>         * src/x86/Gregs.c (linux_scratch_loc): Add XMM registers.
>         (tdep_access_fpreg): Ditto.
>         * src/x86/regname.c: Add XMM registers.
>         * src/x86/is_fpreg.c: Include XMM0 .. XMM7 in floating point
>         registers.
>         * include/libunwind-x86.h (x86_regnum_t): Add UNW_X86_XMM0,
>         UNW_X86_XMM1, UNW_X86_XMM2, UNW_X86_XMM3, UNW_X86_XMM4,
>         UNW_X86_XMM5, UNW_X86_XMM7, UNW_X86_XMM7.
>         (unw_tdep_fpreg_t): Change to a union of possible values.
>
> diff --git a/frysk-imports/libunwind/include/libunwind-x86.h 
> b/frysk-imports/libunwind/include/libunwind-x86.h
> index 38664f9..1e321db 100644
> --- a/frysk-imports/libunwind/include/libunwind-x86.h
> +++ b/frysk-imports/libunwind/include/libunwind-x86.h
> @@ -48,7 +48,11 @@ extern "C" {
>  typedef uint32_t unw_word_t;
>  typedef int32_t unw_sword_t;
>
> -typedef long double unw_tdep_fpreg_t;
> +typedef union {
> +  struct { uint8_t b[4]; } val32;
> +  struct { uint8_t b[10]; } val80;
> +  struct { uint8_t b[16]; } val128;
> +} unw_tdep_fpreg_t;
>
>  typedef enum
>    {
> @@ -131,7 +135,16 @@ typedef enum
>      /* frame info (read-only) */
>      UNW_X86_CFA,
>
> -    UNW_TDEP_LAST_REG = UNW_X86_LDT,
> +    UNW_X86_XMM0,      /* scratch */
> +    UNW_X86_XMM1,      /* scratch */
> +    UNW_X86_XMM2,      /* scratch */
> +    UNW_X86_XMM3,      /* scratch */
> +    UNW_X86_XMM4,      /* scratch */
> +    UNW_X86_XMM5,      /* scratch */
> +    UNW_X86_XMM6,      /* scratch */
> +    UNW_X86_XMM7,      /* scratch */
> +
> +    UNW_TDEP_LAST_REG = UNW_X86_XMM7,
>
>      UNW_TDEP_IP = UNW_X86_EIP,
>      UNW_TDEP_SP = UNW_X86_CFA,
> diff --git a/frysk-imports/libunwind/src/x86/Gregs.c 
> b/frysk-imports/libunwind/src/x86/Gregs.c
> index 68afd37..78cfabc 100644
> --- a/frysk-imports/libunwind/src/x86/Gregs.c
> +++ b/frysk-imports/libunwind/src/x86/Gregs.c
> @@ -97,6 +97,17 @@ linux_scratch_loc (struct cursor *c, unw_regnum_t reg)
>        is_fpstate = 1;
>        off = LINUX_FPSTATE_XMM0_OFF + 8*(reg - UNW_X86_XMM0_lo);
>        break;
> +    case UNW_X86_XMM0:
> +    case UNW_X86_XMM1:
> +    case UNW_X86_XMM2:
> +    case UNW_X86_XMM3:
> +    case UNW_X86_XMM4:
> +    case UNW_X86_XMM5:
> +    case UNW_X86_XMM6:
> +    case UNW_X86_XMM7:
> +      is_fpstate = 1;
> +      off = LINUX_FPSTATE_XMM0_OFF + 16*(reg - UNW_X86_XMM0);
> +      break;
>
>      case UNW_X86_FOP:
>      case UNW_X86_TSS:
> @@ -235,6 +246,14 @@ tdep_access_fpreg (struct cursor *c, unw_regnum_t reg, 
> unw_fpreg_t *valp,
>      case UNW_X86_ST6:
>      case UNW_X86_ST7:
>        /* SSE fp registers */
> +    case UNW_X86_XMM0:
> +    case UNW_X86_XMM1:
> +    case UNW_X86_XMM2:
> +    case UNW_X86_XMM3:
> +    case UNW_X86_XMM4:
> +    case UNW_X86_XMM5:
> +    case UNW_X86_XMM6:
> +    case UNW_X86_XMM7:
>      case UNW_X86_XMM0_lo:
>      case UNW_X86_XMM0_hi:
>      case UNW_X86_XMM1_lo:
> diff --git a/frysk-imports/libunwind/src/x86/is_fpreg.c 
> b/frysk-imports/libunwind/src/x86/is_fpreg.c
> index 6dc5640..8f1536d 100644
> --- a/frysk-imports/libunwind/src/x86/is_fpreg.c
> +++ b/frysk-imports/libunwind/src/x86/is_fpreg.c
> @@ -29,5 +29,6 @@ PROTECTED int
>  unw_is_fpreg (int regnum)
>  {
>    return ((regnum >= UNW_X86_ST0 && regnum <= UNW_X86_ST7)
> -         || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi));
> +         || (regnum >= UNW_X86_XMM0_lo && regnum <= UNW_X86_XMM7_hi)
> +         || (regnum >= UNW_X86_XMM0 && regnum <= UNW_X86_XMM7));
>  }
> diff --git a/frysk-imports/libunwind/src/x86/regname.c 
> b/frysk-imports/libunwind/src/x86/regname.c
> index 824e213..2228510 100644
> --- a/frysk-imports/libunwind/src/x86/regname.c
> +++ b/frysk-imports/libunwind/src/x86/regname.c
> @@ -12,7 +12,9 @@ static const char *regname[] =
>      "xmm6_lo", "xmm6_hi", "xmm7_lo", "xmm7_hi",
>      "mxcsr",
>      "gs", "fs", "es", "ds", "ss", "cs",
> -    "tss", "ldt"
> +    "tss", "ldt",
> +    "cfi",
> +    "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
>    };
>
>  PROTECTED const char *
> diff --git a/frysk-sys/lib/unwind/cni/UnwindH.hxx 
> b/frysk-sys/lib/unwind/cni/UnwindH.hxx
> index 1d13156..04bb212 100644
> --- a/frysk-sys/lib/unwind/cni/UnwindH.hxx
> +++ b/frysk-sys/lib/unwind/cni/UnwindH.hxx
> @@ -286,20 +286,21 @@ 
> lib::unwind::TARGET::getRegister(gnu::gcj::RawDataManaged* cursor,
>      unw_word_t w;
>      unw_fpreg_t fp;
>    } word;
> +  int size;
>    if (unw_is_fpreg(regNum))
> -    {
> -      verifyBounds(offset, length, bytes, start, sizeof(word.fp));
> -      status = unw_get_fpreg((::unw_cursor_t *) cursor,
> -                            (::unw_regnum_t) regNum,
> -                            &word.fp);
> -    }
> +    size = sizeof(word.fp);
>    else
> -    {
> -      verifyBounds(offset, length, bytes, start, sizeof(word.w));
> -      status = unw_get_reg((::unw_cursor_t *) cursor,
> +    size = sizeof(word.w);
> +  verifyBounds(offset, length, bytes, start, size);
> +  if (unw_is_fpreg(regNum))
> +    status = unw_get_fpreg((::unw_cursor_t *) cursor,
>                            (::unw_regnum_t) regNum,
> -                          &word.w);
> -    }
> +                          &word.fp);
> +  else
> +    status = unw_get_reg((::unw_cursor_t *) cursor,
> +                        (::unw_regnum_t) regNum,
> +                        &word.w);
> +  printf("status=%d\n", status);
>    if (status != 0)
>      throwRuntimeException("get register failed");
>    memcpy(elements(bytes) + start, (uint8_t*)&word + offset, length);
> @@ -317,20 +318,20 @@ 
> lib::unwind::TARGET::setRegister(gnu::gcj::RawDataManaged* cursor,
>      unw_word_t w;
>      unw_fpreg_t fp;
>    } word;
> +  int size;
>    if (unw_is_fpreg(regNum))
> -    {
> -      verifyBounds(offset, length, bytes, start, sizeof(word.fp));
> -      status = unw_get_fpreg((::unw_cursor_t *) cursor,
> -                            (::unw_regnum_t) regNum,
> -                            &word.fp);
> -    }
> +    size = sizeof(word.fp);
>    else
> -    {
> -      verifyBounds(offset, length, bytes, start, sizeof(word.w));
> -      status = unw_get_reg((::unw_cursor_t *) cursor,
> +    size = sizeof(word.w);
> +  verifyBounds(offset, length, bytes, start, size);
> +  if (unw_is_fpreg(regNum))
> +    status = unw_get_fpreg((::unw_cursor_t *) cursor,
>                            (::unw_regnum_t) regNum,
> -                          &word.w);
> -    }
> +                          &word.fp);
> +  else
> +    status = unw_get_reg((::unw_cursor_t *) cursor,
> +                        (::unw_regnum_t) regNum,
> +                        &word.w);
>    if (status != 0)
>      throwRuntimeException("set register failed");
>    memcpy((uint8_t*)&word + offset, elements(bytes) + start, length);
>
> _______________________________________________
> Libunwind-devel mailing list
> address@hidden
> http://lists.nongnu.org/mailman/listinfo/libunwind-devel
>
>


-- 
Mosberger Consulting LLC, http://www.mosberger-consulting.com/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]