* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Add support for

TYPE_CODE_DECFLOAT arguments.
	(ppc64_sysv_abi_push_dummy_call) Likewise.
	(get_decimal_float_return_value): New function.
	(do_ppc_sysv_return_value): Add support for TYPE_CODE_DECFLOAT return
	values by calling get_decimal_float_return_value.
	(ppc64_sysv_abi_return_value): Likewise.
This commit is contained in:
Thiago Jung Bauermann 2008-01-30 03:18:39 +00:00
parent 177848379d
commit 1300a2f4b4
2 changed files with 212 additions and 0 deletions

View File

@ -1,3 +1,13 @@
2008-01-30 Thiago Jung Bauermann <bauerman@br.ibm.com>
* ppc-sysv-tdep.c (ppc_sysv_abi_push_dummy_call): Add support for
TYPE_CODE_DECFLOAT arguments.
(ppc64_sysv_abi_push_dummy_call) Likewise.
(get_decimal_float_return_value): New function.
(do_ppc_sysv_return_value): Add support for TYPE_CODE_DECFLOAT return
values by calling get_decimal_float_return_value.
(ppc64_sysv_abi_return_value): Likewise.
2008-01-30 Nick Roberts <nickrob@snap.net.nz>
* mi/mi-cmd-file.c (mi_cmd_file_list_exec_source_file): Add field

View File

@ -241,6 +241,81 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
greg += 4;
}
}
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len <= 8
&& !tdep->soft_float)
{
/* 32-bit and 64-bit decimal floats go in f1 .. f8. They can
end up in memory. */
if (freg <= 8)
{
if (write_pass)
{
gdb_byte regval[MAX_REGISTER_SIZE];
const gdb_byte *p;
/* 32-bit decimal floats are right aligned in the
doubleword. */
if (TYPE_LENGTH (type) == 4)
{
memcpy (regval + 4, val, 4);
p = regval;
}
else
p = val;
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + freg, p);
}
freg++;
}
else
{
argoffset = align_up (argoffset, len);
if (write_pass)
/* Write value in the stack's parameter save area. */
write_memory (sp + argoffset, val, len);
argoffset += len;
}
}
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && len == 16
&& !tdep->soft_float)
{
/* 128-bit decimal floats go in f2 .. f7, always in even/odd
pairs. They can end up in memory, using two doublewords. */
if (freg <= 6)
{
/* Make sure freg is even. */
freg += freg & 1;
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);
}
}
else
{
argoffset = align_up (argoffset, 8);
if (write_pass)
write_memory (sp + argoffset, val, 16);
argoffset += 16;
}
/* If a 128-bit decimal float goes to the stack because only f7
and f8 are free (thus there's no even/odd register pair
available), these registers should be marked as occupied.
Hence we increase freg even when writing to memory. */
freg += 2;
}
else if (len == 16
&& TYPE_CODE (type) == TYPE_CODE_ARRAY
&& TYPE_VECTOR (type)
@ -386,6 +461,70 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
return sp;
}
/* Handle the return-value conventions for Decimal Floating Point values
in both ppc32 and ppc64, which are the same. */
static int
get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype,
struct regcache *regcache, gdb_byte *readbuf,
const gdb_byte *writebuf)
{
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
gdb_assert (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT);
/* 32-bit and 64-bit decimal floats in f1. */
if (TYPE_LENGTH (valtype) <= 8)
{
if (writebuf != NULL)
{
gdb_byte regval[MAX_REGISTER_SIZE];
const gdb_byte *p;
/* 32-bit decimal float is right aligned in the doubleword. */
if (TYPE_LENGTH (valtype) == 4)
{
memcpy (regval + 4, writebuf, 4);
p = regval;
}
else
p = writebuf;
regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 1, p);
}
if (readbuf != NULL)
{
regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 1, readbuf);
/* Left align 32-bit decimal float. */
if (TYPE_LENGTH (valtype) == 4)
memcpy (readbuf, readbuf + 4, 4);
}
}
/* 128-bit decimal floats in f2,f3. */
else if (TYPE_LENGTH (valtype) == 16)
{
if (writebuf != NULL || readbuf != NULL)
{
int i;
for (i = 0; i < 2; i++)
{
if (writebuf != NULL)
regcache_cooked_write (regcache, tdep->ppc_fp0_regnum + 2 + i,
writebuf + i * 8);
if (readbuf != NULL)
regcache_cooked_read (regcache, tdep->ppc_fp0_regnum + 2 + i,
readbuf + i * 8);
}
}
}
else
/* Can't happen. */
internal_error (__FILE__, __LINE__, "Unknown decimal float size.");
return RETURN_VALUE_REGISTER_CONVENTION;
}
/* Handle the return-value conventions specified by the SysV 32-bit
PowerPC ABI (including all the supplements):
@ -501,6 +640,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type,
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT && !tdep->soft_float)
return get_decimal_float_return_value (gdbarch, type, regcache, readbuf,
writebuf);
else if ((TYPE_CODE (type) == TYPE_CODE_INT
|| TYPE_CODE (type) == TYPE_CODE_CHAR
|| TYPE_CODE (type) == TYPE_CODE_BOOL
@ -906,6 +1048,63 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
greg += 2;
gparam = align_up (gparam + TYPE_LENGTH (type), tdep->wordsize);
}
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT
&& TYPE_LENGTH (type) <= 8)
{
/* 32-bit and 64-bit decimal floats go in f1 .. f13. They can
end up in memory. */
if (write_pass)
{
gdb_byte regval[MAX_REGISTER_SIZE];
const gdb_byte *p;
/* 32-bit decimal floats are right aligned in the
doubleword. */
if (TYPE_LENGTH (type) == 4)
{
memcpy (regval + 4, val, 4);
p = regval;
}
else
p = val;
/* Write value in the stack's parameter save area. */
write_memory (gparam, p, 8);
if (freg <= 13)
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + freg, p);
}
freg++;
greg++;
/* Always consume parameter stack space. */
gparam = align_up (gparam + 8, tdep->wordsize);
}
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT &&
TYPE_LENGTH (type) == 16)
{
/* 128-bit decimal floats go in f2 .. f12, always in even/odd
pairs. They can end up in memory, using two doublewords. */
if (write_pass)
{
if (freg <= 12)
{
/* Make sure freg is even. */
freg += freg & 1;
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + freg, val);
regcache_cooked_write (regcache,
tdep->ppc_fp0_regnum + freg + 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)
@ -1133,6 +1332,9 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype,
}
return RETURN_VALUE_REGISTER_CONVENTION;
}
if (TYPE_CODE (valtype) == TYPE_CODE_DECFLOAT)
return get_decimal_float_return_value (gdbarch, valtype, regcache, readbuf,
writebuf);
/* Integers in r3. */
if ((TYPE_CODE (valtype) == TYPE_CODE_INT
|| TYPE_CODE (valtype) == TYPE_CODE_ENUM)