mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-24 18:44:20 +08:00
2007-11-07 Joseph Myers <joseph@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com> * ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Right-align struct values smaller than one doubleword; left-align those larger. Pass structs containing a single floating-point value in registers.
This commit is contained in:
parent
b14d30e141
commit
36815e57a6
@ -1,3 +1,11 @@
|
|||||||
|
2007-11-07 Joseph Myers <joseph@codesourcery.com>
|
||||||
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
* ppc-sysv-tdep.c (ppc64_sysv_abi_push_dummy_call): Right-align
|
||||||
|
struct values smaller than one doubleword; left-align those
|
||||||
|
larger. Pass structs containing a single floating-point value in
|
||||||
|
registers.
|
||||||
|
|
||||||
2007-11-07 Joseph Myers <joseph@codesourcery.com>
|
2007-11-07 Joseph Myers <joseph@codesourcery.com>
|
||||||
Daniel Jacobowitz <dan@codesourcery.com>
|
Daniel Jacobowitz <dan@codesourcery.com>
|
||||||
|
|
||||||
|
@ -977,22 +977,17 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||||||
if (len > tdep->wordsize)
|
if (len > tdep->wordsize)
|
||||||
len = tdep->wordsize;
|
len = tdep->wordsize;
|
||||||
memset (regval, 0, sizeof regval);
|
memset (regval, 0, sizeof regval);
|
||||||
/* WARNING: cagney/2003-09-21: As best I can
|
/* The ABI (version 1.9) specifies that values
|
||||||
tell, the ABI specifies that the value should
|
smaller than one doubleword are right-aligned
|
||||||
be left aligned. Unfortunately, GCC doesn't
|
and those larger are left-aligned. GCC
|
||||||
do this - it instead right aligns even sized
|
versions before 3.4 implemented this
|
||||||
values and puts odd sized values on the
|
incorrectly; see
|
||||||
stack. Work around that by putting both a
|
<http://gcc.gnu.org/gcc-3.4/powerpc-abi.html>. */
|
||||||
left and right aligned value into the
|
if (byte == 0)
|
||||||
register (hopefully no one notices :-^).
|
|
||||||
Arrrgh! */
|
|
||||||
/* Left aligned (8 byte values such as pointers
|
|
||||||
fill the buffer). */
|
|
||||||
memcpy (regval, val + byte, len);
|
|
||||||
/* Right aligned (but only if even). */
|
|
||||||
if (len == 1 || len == 2 || len == 4)
|
|
||||||
memcpy (regval + tdep->wordsize - len,
|
memcpy (regval + tdep->wordsize - len,
|
||||||
val + byte, len);
|
val + byte, len);
|
||||||
|
else
|
||||||
|
memcpy (regval, val + byte, len);
|
||||||
regcache_cooked_write (regcache, greg, regval);
|
regcache_cooked_write (regcache, greg, regval);
|
||||||
}
|
}
|
||||||
greg++;
|
greg++;
|
||||||
@ -1006,11 +1001,57 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
|
|||||||
value to memory. Fortunately, doing this
|
value to memory. Fortunately, doing this
|
||||||
simplifies the code. */
|
simplifies the code. */
|
||||||
write_memory (gparam, val, TYPE_LENGTH (type));
|
write_memory (gparam, val, TYPE_LENGTH (type));
|
||||||
if (write_pass)
|
if (freg <= 13
|
||||||
/* WARNING: cagney/2004-06-20: It appears that GCC
|
&& TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||||||
likes to put structures containing a single
|
&& TYPE_NFIELDS (type) == 1
|
||||||
floating-point member in an FP register instead of
|
&& TYPE_LENGTH (type) <= 16)
|
||||||
general general purpose. */
|
{
|
||||||
|
/* The ABI (version 1.9) specifies that structs
|
||||||
|
containing a single floating-point value, at any
|
||||||
|
level of nesting of single-member structs, are
|
||||||
|
passed in floating-point registers. */
|
||||||
|
while (TYPE_CODE (type) == TYPE_CODE_STRUCT
|
||||||
|
&& TYPE_NFIELDS (type) == 1)
|
||||||
|
type = check_typedef (TYPE_FIELD_TYPE (type, 0));
|
||||||
|
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
||||||
|
{
|
||||||
|
if (TYPE_LENGTH (type) <= 8)
|
||||||
|
{
|
||||||
|
if (write_pass)
|
||||||
|
{
|
||||||
|
gdb_byte regval[MAX_REGISTER_SIZE];
|
||||||
|
struct type *regtype
|
||||||
|
= register_type (gdbarch,
|
||||||
|
tdep->ppc_fp0_regnum);
|
||||||
|
convert_typed_floating (val, type, regval,
|
||||||
|
regtype);
|
||||||
|
regcache_cooked_write (regcache,
|
||||||
|
(tdep->ppc_fp0_regnum
|
||||||
|
+ freg),
|
||||||
|
regval);
|
||||||
|
}
|
||||||
|
freg++;
|
||||||
|
}
|
||||||
|
else if (TYPE_LENGTH (type) == 16
|
||||||
|
&& (gdbarch_long_double_format (current_gdbarch)
|
||||||
|
== floatformats_ibm_long_double))
|
||||||
|
{
|
||||||
|
if (write_pass)
|
||||||
|
{
|
||||||
|
regcache_cooked_write (regcache,
|
||||||
|
(tdep->ppc_fp0_regnum
|
||||||
|
+ freg),
|
||||||
|
val);
|
||||||
|
if (freg <= 12)
|
||||||
|
regcache_cooked_write (regcache,
|
||||||
|
(tdep->ppc_fp0_regnum
|
||||||
|
+ freg + 1),
|
||||||
|
val + 8);
|
||||||
|
}
|
||||||
|
freg += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
/* Always consume parameter stack space. */
|
/* Always consume parameter stack space. */
|
||||||
gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
|
gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user