summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2012-10-23 18:16:52 +0000
committerMark Kettenis <kettenis@gnu.org>2012-10-23 18:16:52 +0000
commite8d292014c88266e35d7cff759d4a65fab0f6470 (patch)
tree301cf75069995357e829794b2f7cc483489c3bab
parente7e9e7efbed40700dc661edb5b487b3f0c28b373 (diff)
downloadgdb-e8d292014c88266e35d7cff759d4a65fab0f6470.tar.gz
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.
-rw-r--r--gdb/ChangeLog10
-rw-r--r--gdb/amd64-tdep.c41
-rw-r--r--gdb/amd64-tdep.h2
3 files changed, 53 insertions, 0 deletions
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 <kettenis@gnu.org>
+
+ 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 <brobecker@adacore.com>
* 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,