aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd64-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2012-10-23 18:16:55 +0000
committerMark Kettenis <kettenis@gnu.org>2012-10-23 18:16:55 +0000
commit7f7930dd889bc0dcfd56b5dc362eb805b1f93560 (patch)
tree0df5344756f59cfd322dbdbf7b4eea78f5e1f3ea /gdb/amd64-tdep.c
parent9ece1fa9916f3105bc410a454d23e3d13021e3ac (diff)
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.
Diffstat (limited to 'gdb/amd64-tdep.c')
-rw-r--r--gdb/amd64-tdep.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 9cee464bc6..a4172fc2dc 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);