From: Mark Kettenis Date: Tue, 23 Oct 2012 18:16:55 +0000 (+0000) Subject: PR gdb/12796 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=7f7930dd889bc0dcfd56b5dc362eb805b1f93560;p=binutils-gdb.git PR gdb/12796 PR gdb/12798 PR gdb/12800 * amd64-tdep.h (enum amd64_regnum): Add AMD64_ST1_REGNUM and AMD64_FTAG_REGNUM. * amd64-tdep.c (amd64_classify): Classify complex types. (amd64_return_value): Handle the COMPLEX_X87 class. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index d3d534d7200..2ccc5d79126 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,13 @@ +2012-10-23 Mark Kettenis + + PR gdb/12796 + PR gdb/12798 + PR gdb/12800 + * amd64-tdep.h (enum amd64_regnum): Add AMD64_ST1_REGNUM and + AMD64_FTAG_REGNUM. + * amd64-tdep.c (amd64_classify): Classify complex types. + (amd64_return_value): Handle the COMPLEX_X87 class. + 2012-10-23 Joel Brobecker * rs6000-aix-tdep.c (rs6000_aix_auto_wide_charset): New function. diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 9cee464bc69..a4172fc2dc1 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -586,6 +586,23 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2]) /* Class X87 and X87UP. */ class[0] = AMD64_X87, class[1] = AMD64_X87UP; + /* Arguments of complex T where T is one of the types float or + double get treated as if they are implemented as: + + struct complexT { + T real; + T imag; + }; */ + else if (code == TYPE_CODE_COMPLEX && len == 8) + class[0] = AMD64_SSE; + else if (code == TYPE_CODE_COMPLEX && len == 16) + class[0] = class[1] = AMD64_SSE; + + /* A variable of type complex long double is classified as type + COMPLEX_X87. */ + else if (code == TYPE_CODE_COMPLEX && len == 32) + class[0] = AMD64_COMPLEX_X87; + /* Aggregates. */ else if (code == TYPE_CODE_ARRAY || code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION) @@ -636,6 +653,30 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function, return RETURN_VALUE_ABI_RETURNS_ADDRESS; } + /* 8. If the class is COMPLEX_X87, the real part of the value is + returned in %st0 and the imaginary part in %st1. */ + if (class[0] == AMD64_COMPLEX_X87) + { + if (readbuf) + { + regcache_raw_read (regcache, AMD64_ST0_REGNUM, readbuf); + regcache_raw_read (regcache, 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); + + /* Fix up the tag word such that both %st(0) and %st(1) are + marked as valid. */ + regcache_raw_write_unsigned (regcache, AMD64_FTAG_REGNUM, 0xfff); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + gdb_assert (class[1] != AMD64_MEMORY); gdb_assert (len <= 16); diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index cb901cc0ce7..eba0d6dc934 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -57,8 +57,10 @@ enum amd64_regnum AMD64_FS_REGNUM, /* %fs */ AMD64_GS_REGNUM, /* %gs */ AMD64_ST0_REGNUM = 24, /* %st0 */ + AMD64_ST1_REGNUM, /* %st1 */ AMD64_FCTRL_REGNUM = AMD64_ST0_REGNUM + 8, AMD64_FSTAT_REGNUM = AMD64_ST0_REGNUM + 9, + AMD64_FTAG_REGNUM = AMD64_ST0_REGNUM + 10, AMD64_XMM0_REGNUM = 40, /* %xmm0 */ AMD64_XMM1_REGNUM, /* %xmm1 */ AMD64_MXCSR_REGNUM = AMD64_XMM0_REGNUM + 16,