diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/sh-tdep.c | 26 |
2 files changed, 29 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 41f7dfe..d170797 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,8 @@ +2003-10-10 Corinna Vinschen <vinschen@redhat.com> + + * sh-tdep.c (sh_use_struct_convention): Clean up to have a + more readable code. Accomodate passing of bitfields. + 2003-10-10 Andrew Cagney <cagney@redhat.com> * Makefile.in (ppc-sysv-tdep.o): Add $(gdb_assert_h). diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index a220493..eee7698 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -589,8 +589,30 @@ sh_use_struct_convention (int gcc_p, struct type *type) { int len = TYPE_LENGTH (type); int nelem = TYPE_NFIELDS (type); - return ((len != 1 && len != 2 && len != 4 && len != 8) || nelem != 1) && - (len != 8 || TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) != 4); + + /* Non-power of 2 length types and types bigger than 8 bytes (which don't + fit in two registers anyway) use struct convention. */ + if (len != 1 && len != 2 && len != 4 && len != 8) + return 1; + + /* Scalar types and aggregate types with exactly one field are aligned + by definition. They are returned in registers. */ + if (nelem <= 1) + return 0; + + /* If the first field in the aggregate has the same length as the entire + aggregate type, the type is returned in registers. */ + if (TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == len) + return 0; + + /* If the size of the aggregate is 8 bytes and the first field is + of size 4 bytes its alignment is equal to long long's alignment, + so it's returned in registers. */ + if (len == 8 && TYPE_LENGTH (TYPE_FIELD_TYPE (type, 0)) == 4) + return 0; + + /* Otherwise use struct convention. */ + return 1; } /* Extract from an array REGBUF containing the (raw) register state |