From 7f7930dd889bc0dcfd56b5dc362eb805b1f93560 Mon Sep 17 00:00:00 2001 From: Mark Kettenis Date: Tue, 23 Oct 2012 18:16:55 +0000 Subject: 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. --- gdb/amd64-tdep.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'gdb/amd64-tdep.c') diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 9cee464..a4172fc 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); -- cgit v1.1