aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2005-08-17 07:44:13 +0000
committerMark Kettenis <kettenis@gnu.org>2005-08-17 07:44:13 +0000
commit61bf9ae086ed8e0107ab376dd19659e6f1c923a0 (patch)
tree80d79ecd60d87d30868de9b53a4025a3b2cef5f7
parent24dc748d60dcf80ab486ba7b99e97f1180b9158e (diff)
downloadgdb-61bf9ae086ed8e0107ab376dd19659e6f1c923a0.zip
gdb-61bf9ae086ed8e0107ab376dd19659e6f1c923a0.tar.gz
gdb-61bf9ae086ed8e0107ab376dd19659e6f1c923a0.tar.bz2
* ppc-sysv-tdep.c (do_ppc_sysv_return_value): Fix the code that
deals with the broken GCC convention.
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/ppc-sysv-tdep.c61
2 files changed, 26 insertions, 40 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index d3951b1..3ff6d7e 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2005-08-17 Mark Kettenis <kettenis@gnu.org>
+
+ * ppc-sysv-tdep.c (do_ppc_sysv_return_value): Fix the code that
+ deals with the broken GCC convention.
+
2005-08-16 Mark Kettenis <kettenis@gnu.org>
* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Set condition
diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c
index 3824c99..4285077 100644
--- a/gdb/ppc-sysv-tdep.c
+++ b/gdb/ppc-sysv-tdep.c
@@ -451,52 +451,33 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
}
if (broken_gcc && TYPE_LENGTH (type) <= 8)
{
+ /* GCC screwed up for structures or unions whose size is less
+ than or equal to 8 bytes.. Instead of left-aligning, it
+ right-aligns the data into the buffer formed by r3, r4. */
+ gdb_byte regvals[MAX_REGISTER_SIZE * 2];
+ int len = TYPE_LENGTH (type);
+ int offset = (2 * tdep->wordsize - len) % tdep->wordsize;
+
if (readbuf)
{
- /* GCC screwed up. The last register isn't "left" aligned.
- Need to extract the least significant part of each
- register and then store that. */
- /* Transfer any full words. */
- int word = 0;
- while (1)
- {
- ULONGEST reg;
- int len = TYPE_LENGTH (type) - word * tdep->wordsize;
- if (len <= 0)
- break;
- if (len > tdep->wordsize)
- len = tdep->wordsize;
- regcache_cooked_read_unsigned (regcache,
- tdep->ppc_gp0_regnum + 3 + word,
- &reg);
- store_unsigned_integer (((bfd_byte *) readbuf
- + word * tdep->wordsize), len, reg);
- word++;
- }
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (len > tdep->wordsize)
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
+ memcpy (readbuf, regvals + offset, len);
}
if (writebuf)
{
- /* GCC screwed up. The last register isn't "left" aligned.
- Need to extract the least significant part of each
- register and then store that. */
- /* Transfer any full words. */
- int word = 0;
- while (1)
- {
- ULONGEST reg;
- int len = TYPE_LENGTH (type) - word * tdep->wordsize;
- if (len <= 0)
- break;
- if (len > tdep->wordsize)
- len = tdep->wordsize;
- reg = extract_unsigned_integer (((const bfd_byte *) writebuf
- + word * tdep->wordsize), len);
- regcache_cooked_write_unsigned (regcache,
- tdep->ppc_gp0_regnum + 3 + word,
- reg);
- word++;
- }
+ memset (regvals, 0, sizeof regvals);
+ memcpy (regvals + offset, writebuf, len);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ regvals + 0 * tdep->wordsize);
+ if (len > tdep->wordsize)
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ regvals + 1 * tdep->wordsize);
}
+
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_LENGTH (type) <= 8)