int argspace = 0; /* 0 is an initial wrong guess. */
int write_pass;
+ gdb_assert (tdep->wordsize == 4);
+
regcache_cooked_read_unsigned (regcache,
gdbarch_sp_regnum (current_gdbarch),
&saved_sp);
int len = TYPE_LENGTH (type);
const bfd_byte *val = value_contents (arg);
- if (TYPE_CODE (type) == TYPE_CODE_FLT
- && ppc_floating_point_unit_p (current_gdbarch) && len <= 8)
+ if (TYPE_CODE (type) == TYPE_CODE_FLT && len <= 8
+ && !tdep->soft_float)
{
/* Floating point value converted to "double" then
passed in an FP register, when the registers run out,
argoffset += 8;
}
}
- else if (len == 8 && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
- || (!ppc_floating_point_unit_p (current_gdbarch) && TYPE_CODE (type) == TYPE_CODE_FLT))) /* double */
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && len == 16
+ && !tdep->soft_float
+ && (gdbarch_long_double_format (current_gdbarch)
+ == floatformats_ibm_long_double))
{
- /* "long long" or "double" passed in an odd/even
+ /* IBM long double passed in two FP registers if
+ available, otherwise 8-byte aligned stack. */
+ if (freg <= 7)
+ {
+ if (write_pass)
+ {
+ regcache_cooked_write (regcache,
+ tdep->ppc_fp0_regnum + freg,
+ val);
+ regcache_cooked_write (regcache,
+ tdep->ppc_fp0_regnum + freg + 1,
+ val + 8);
+ }
+ freg += 2;
+ }
+ else
+ {
+ argoffset = align_up (argoffset, 8);
+ if (write_pass)
+ write_memory (sp + argoffset, val, len);
+ argoffset += 16;
+ }
+ }
+ else if (len == 8
+ && (TYPE_CODE (type) == TYPE_CODE_INT /* long long */
+ || TYPE_CODE (type) == TYPE_CODE_FLT)) /* double */
+ {
+ /* "long long" or soft-float "double" passed in an odd/even
register pair with the low addressed word in the odd
register and the high addressed word in the even
register, or when the registers run out an 8 byte
write_memory (sp + argoffset, val, len);
argoffset += 8;
}
- else if (tdep->wordsize == 8)
- {
- if (write_pass)
- regcache_cooked_write (regcache,
- tdep->ppc_gp0_regnum + greg, val);
- greg += 1;
- }
else
{
/* Must start on an odd register - r3/r4 etc. */
greg += 2;
}
}
+ else if (len == 16 && TYPE_CODE (type) == TYPE_CODE_FLT
+ && (gdbarch_long_double_format (current_gdbarch)
+ == floatformats_ibm_long_double))
+ {
+ /* Soft-float IBM long double passed in four consecutive
+ registers, or on the stack. The registers are not
+ necessarily odd/even pairs. */
+ if (greg > 7)
+ {
+ greg = 11;
+ argoffset = align_up (argoffset, 8);
+ if (write_pass)
+ write_memory (sp + argoffset, val, len);
+ argoffset += 16;
+ }
+ else
+ {
+ if (write_pass)
+ {
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg + 0,
+ val + 0);
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg + 1,
+ val + 4);
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg + 2,
+ val + 8);
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg + 3,
+ val + 12);
+ }
+ greg += 4;
+ }
+ }
else if (len == 16
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
+ && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
{
/* Vector parameter passed in an Altivec register, or
when that runs out, 16 byte aligned stack location. */
}
else if (len == 8
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
+ && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_SPE)
{
/* Vector parameter passed in an e500 register, or when
that runs out, 8 byte aligned stack location. Note
|| TYPE_CODE (type) == TYPE_CODE_STRUCT
|| TYPE_CODE (type) == TYPE_CODE_UNION)
{
- /* Structs and large values are put on an 8 byte
- aligned stack ... */
- structoffset = align_up (structoffset, 8);
+ /* Structs and large values are put in an
+ aligned stack slot ... */
+ if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && len >= 16)
+ structoffset = align_up (structoffset, 16);
+ else
+ structoffset = align_up (structoffset, 8);
+
if (write_pass)
write_memory (sp + structoffset, val, len);
/* ... and then a "word" pointing to that address is
static enum return_value_convention
do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
- struct regcache *regcache, void *readbuf,
- const void *writebuf, int broken_gcc)
+ struct regcache *regcache, gdb_byte *readbuf,
+ const gdb_byte *writebuf, int broken_gcc)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (tdep->wordsize == 4);
if (TYPE_CODE (type) == TYPE_CODE_FLT
&& TYPE_LENGTH (type) <= 8
- && ppc_floating_point_unit_p (gdbarch))
+ && !tdep->soft_float)
{
if (readbuf)
{
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 16
+ && !tdep->soft_float
+ && (gdbarch_long_double_format (current_gdbarch)
+ == floatformats_ibm_long_double))
+ {
+ /* IBM long double stored in f1 and f2. */
+ if (readbuf)
+ {
+ regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf);
+ regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2,
+ readbuf + 8);
+ }
+ if (writebuf)
+ {
+ regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, writebuf);
+ regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2,
+ writebuf + 8);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
+ if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 16
+ && (gdbarch_long_double_format (current_gdbarch)
+ == floatformats_ibm_long_double))
+ {
+ /* Soft-float IBM long double stored in r3, r4, r5, r6. */
+ if (readbuf)
+ {
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3, readbuf);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ readbuf + 4);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
+ readbuf + 8);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
+ readbuf + 12);
+ }
+ if (writebuf)
+ {
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3, writebuf);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ writebuf + 4);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
+ writebuf + 8);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
+ writebuf + 12);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
if ((TYPE_CODE (type) == TYPE_CODE_INT && TYPE_LENGTH (type) == 8)
|| (TYPE_CODE (type) == TYPE_CODE_FLT && TYPE_LENGTH (type) == 8))
{
{
/* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
- (bfd_byte *) readbuf + 0);
+ readbuf + 0);
regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
- (bfd_byte *) readbuf + 4);
+ readbuf + 4);
}
if (writebuf)
{
/* A long long, or a double stored in the 32 bit r3/r4. */
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
- (const bfd_byte *) writebuf + 0);
+ writebuf + 0);
regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
- (const bfd_byte *) writebuf + 4);
+ writebuf + 4);
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
- if (TYPE_CODE (type) == TYPE_CODE_INT
- && TYPE_LENGTH (type) <= tdep->wordsize)
+ else if ((TYPE_CODE (type) == TYPE_CODE_INT
+ || TYPE_CODE (type) == TYPE_CODE_CHAR
+ || TYPE_CODE (type) == TYPE_CODE_BOOL
+ || TYPE_CODE (type) == TYPE_CODE_PTR
+ || TYPE_CODE (type) == TYPE_CODE_REF
+ || TYPE_CODE (type) == TYPE_CODE_ENUM)
+ && TYPE_LENGTH (type) <= tdep->wordsize)
{
if (readbuf)
{
}
if (TYPE_LENGTH (type) == 16
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (type) && tdep->ppc_vr0_regnum >= 0)
+ && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_ALTIVEC)
{
if (readbuf)
{
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
+ if (TYPE_LENGTH (type) == 16
+ && TYPE_CODE (type) == TYPE_CODE_ARRAY
+ && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_GENERIC)
+ {
+ /* GCC -maltivec -mabi=no-altivec returns vectors in r3/r4/r5/r6.
+ GCC without AltiVec returns them in memory, but it warns about
+ ABI risks in that case; we don't try to support it. */
+ if (readbuf)
+ {
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 3,
+ readbuf + 0);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 4,
+ readbuf + 4);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 5,
+ readbuf + 8);
+ regcache_cooked_read (regcache, tdep->ppc_gp0_regnum + 6,
+ readbuf + 12);
+ }
+ if (writebuf)
+ {
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 3,
+ writebuf + 0);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 4,
+ writebuf + 4);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 5,
+ writebuf + 8);
+ regcache_cooked_write (regcache, tdep->ppc_gp0_regnum + 6,
+ writebuf + 12);
+ }
+ return RETURN_VALUE_REGISTER_CONVENTION;
+ }
if (TYPE_LENGTH (type) == 8
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
- && TYPE_VECTOR (type) && tdep->ppc_ev0_regnum >= 0)
+ && TYPE_VECTOR (type)
+ && tdep->vector_abi == POWERPC_VEC_SPE)
{
/* The e500 ABI places return values for the 64-bit DSP types
(__ev64_opaque__) in r3. However, in GDB-speak, ev3
the possible values of tdep->wordsize. */
gdb_assert (tdep->wordsize == 8);
+ /* This function exists to support a calling convention that
+ requires floating-point registers. It shouldn't be used on
+ processors that lack them. */
+ gdb_assert (ppc_floating_point_unit_p (gdbarch));
+
/* By this stage in the proceedings, SP has been decremented by "red
zone size" + "struct return size". Fetch the stack-pointer from
before this and use that as the BACK_CHAIN. */
memory. */
if (write_pass)
{
- if (ppc_floating_point_unit_p (current_gdbarch)
- && freg <= 13)
+ if (freg <= 13)
{
gdb_byte regval[MAX_REGISTER_SIZE];
struct type *regtype
greg++;
gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
}
+ else if (TYPE_CODE (type) == TYPE_CODE_FLT
+ && TYPE_LENGTH (type) == 16
+ && (gdbarch_long_double_format (current_gdbarch)
+ == floatformats_ibm_long_double))
+ {
+ /* IBM long double stored in two doublewords of the
+ parameter save area and corresponding registers. */
+ if (write_pass)
+ {
+ if (!tdep->soft_float && freg <= 13)
+ {
+ 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);
+ }
+ if (greg <= 10)
+ {
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg,
+ val);
+ if (greg <= 9)
+ regcache_cooked_write (regcache,
+ tdep->ppc_gp0_regnum + greg + 1,
+ val + 8);
+ }
+ write_memory (gparam, val, TYPE_LENGTH (type));
+ }
+ freg += 2;
+ greg += 2;
+ gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
+ }
else if (TYPE_LENGTH (type) == 16 && TYPE_VECTOR (type)
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
&& tdep->ppc_vr0_regnum >= 0)
}
-/* The 64 bit ABI retun value convention.
+/* The 64 bit ABI return value convention.
Return non-zero if the return-value is stored in a register, return
0 if the return-value is instead stored on the stack (a.k.a.,