mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-21 02:24:17 +08:00
S390: Re-arrange implementation of s390_return_value
Move related logic in the implementation of s390_return_value closer together. This makes it easier to read and extend. gdb/ChangeLog: * s390-linux-tdep.c (s390_return_value_convention): Remove function. Inline its logic... (s390_return_value): ...here. Instead, move the handling of the "register" return value convention... (s390_register_return_value): ...here. New function.
This commit is contained in:

committed by
Andreas Krebbel

parent
80f7532016
commit
4e65a17e62
@ -1,3 +1,11 @@
|
|||||||
|
2015-04-27 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
* s390-linux-tdep.c (s390_return_value_convention): Remove
|
||||||
|
function. Inline its logic...
|
||||||
|
(s390_return_value): ...here. Instead, move the handling of the
|
||||||
|
"register" return value convention...
|
||||||
|
(s390_register_return_value): ...here. New function.
|
||||||
|
|
||||||
2015-04-27 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
2015-04-27 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||||
|
|
||||||
* s390-linux-tdep.c
|
* s390-linux-tdep.c
|
||||||
|
@ -2708,13 +2708,75 @@ s390_frame_align (struct gdbarch *gdbarch, CORE_ADDR addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Function return value access. */
|
/* Helper for s390_return_value: Set or retrieve a function return
|
||||||
|
value if it resides in a register. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
s390_register_return_value (struct gdbarch *gdbarch, struct type *type,
|
||||||
|
struct regcache *regcache,
|
||||||
|
gdb_byte *out, const gdb_byte *in)
|
||||||
|
{
|
||||||
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||||
|
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
||||||
|
int length = TYPE_LENGTH (type);
|
||||||
|
int code = TYPE_CODE (type);
|
||||||
|
|
||||||
|
if (code == TYPE_CODE_FLT || code == TYPE_CODE_DECFLOAT)
|
||||||
|
{
|
||||||
|
/* Float-like value: left-aligned in f0. */
|
||||||
|
if (in != NULL)
|
||||||
|
regcache_cooked_write_part (regcache, S390_F0_REGNUM,
|
||||||
|
0, length, in);
|
||||||
|
else
|
||||||
|
regcache_cooked_read_part (regcache, S390_F0_REGNUM,
|
||||||
|
0, length, out);
|
||||||
|
}
|
||||||
|
else if (length <= word_size)
|
||||||
|
{
|
||||||
|
/* Integer: zero- or sign-extended in r2. */
|
||||||
|
if (out != NULL)
|
||||||
|
regcache_cooked_read_part (regcache, S390_R2_REGNUM,
|
||||||
|
word_size - length, length, out);
|
||||||
|
else if (TYPE_UNSIGNED (type))
|
||||||
|
regcache_cooked_write_unsigned
|
||||||
|
(regcache, S390_R2_REGNUM,
|
||||||
|
extract_unsigned_integer (in, length, byte_order));
|
||||||
|
else
|
||||||
|
regcache_cooked_write_signed
|
||||||
|
(regcache, S390_R2_REGNUM,
|
||||||
|
extract_signed_integer (in, length, byte_order));
|
||||||
|
}
|
||||||
|
else if (length == 2 * word_size)
|
||||||
|
{
|
||||||
|
/* Double word: in r2 and r3. */
|
||||||
|
if (in != NULL)
|
||||||
|
{
|
||||||
|
regcache_cooked_write (regcache, S390_R2_REGNUM, in);
|
||||||
|
regcache_cooked_write (regcache, S390_R3_REGNUM,
|
||||||
|
in + word_size);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
regcache_cooked_read (regcache, S390_R2_REGNUM, out);
|
||||||
|
regcache_cooked_read (regcache, S390_R3_REGNUM,
|
||||||
|
out + word_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
internal_error (__FILE__, __LINE__, _("invalid return type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Implement the 'return_value' gdbarch method. */
|
||||||
|
|
||||||
static enum return_value_convention
|
static enum return_value_convention
|
||||||
s390_return_value_convention (struct gdbarch *gdbarch, struct type *type)
|
s390_return_value (struct gdbarch *gdbarch, struct value *function,
|
||||||
|
struct type *type, struct regcache *regcache,
|
||||||
|
gdb_byte *out, const gdb_byte *in)
|
||||||
{
|
{
|
||||||
if (TYPE_LENGTH (type) > 8)
|
enum return_value_convention rvc;
|
||||||
return RETURN_VALUE_STRUCT_CONVENTION;
|
|
||||||
|
type = check_typedef (type);
|
||||||
|
|
||||||
switch (TYPE_CODE (type))
|
switch (TYPE_CODE (type))
|
||||||
{
|
{
|
||||||
@ -2722,96 +2784,22 @@ s390_return_value_convention (struct gdbarch *gdbarch, struct type *type)
|
|||||||
case TYPE_CODE_UNION:
|
case TYPE_CODE_UNION:
|
||||||
case TYPE_CODE_ARRAY:
|
case TYPE_CODE_ARRAY:
|
||||||
case TYPE_CODE_COMPLEX:
|
case TYPE_CODE_COMPLEX:
|
||||||
return RETURN_VALUE_STRUCT_CONVENTION;
|
rvc = RETURN_VALUE_STRUCT_CONVENTION;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return RETURN_VALUE_REGISTER_CONVENTION;
|
rvc = TYPE_LENGTH (type) <= 8
|
||||||
|
? RETURN_VALUE_REGISTER_CONVENTION
|
||||||
|
: RETURN_VALUE_STRUCT_CONVENTION;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static enum return_value_convention
|
if (in != NULL || out != NULL)
|
||||||
s390_return_value (struct gdbarch *gdbarch, struct value *function,
|
|
||||||
struct type *type, struct regcache *regcache,
|
|
||||||
gdb_byte *out, const gdb_byte *in)
|
|
||||||
{
|
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
||||||
int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
|
||||||
enum return_value_convention rvc;
|
|
||||||
int length;
|
|
||||||
|
|
||||||
type = check_typedef (type);
|
|
||||||
rvc = s390_return_value_convention (gdbarch, type);
|
|
||||||
length = TYPE_LENGTH (type);
|
|
||||||
|
|
||||||
if (in)
|
|
||||||
{
|
{
|
||||||
switch (rvc)
|
if (rvc == RETURN_VALUE_REGISTER_CONVENTION)
|
||||||
{
|
s390_register_return_value (gdbarch, type, regcache, out, in);
|
||||||
case RETURN_VALUE_REGISTER_CONVENTION:
|
else if (in != NULL)
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT
|
error (_("Cannot set function return value."));
|
||||||
|| TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
else
|
||||||
{
|
error (_("Function return value unknown."));
|
||||||
/* When we store a single-precision value in an FP register,
|
|
||||||
it occupies the leftmost bits. */
|
|
||||||
regcache_cooked_write_part (regcache, S390_F0_REGNUM,
|
|
||||||
0, length, in);
|
|
||||||
}
|
|
||||||
else if (length <= word_size)
|
|
||||||
{
|
|
||||||
/* Integer arguments are always extended to word size. */
|
|
||||||
if (TYPE_UNSIGNED (type))
|
|
||||||
regcache_cooked_write_unsigned (regcache, S390_R2_REGNUM,
|
|
||||||
extract_unsigned_integer (in, length, byte_order));
|
|
||||||
else
|
|
||||||
regcache_cooked_write_signed (regcache, S390_R2_REGNUM,
|
|
||||||
extract_signed_integer (in, length, byte_order));
|
|
||||||
}
|
|
||||||
else if (length == 2*word_size)
|
|
||||||
{
|
|
||||||
regcache_cooked_write (regcache, S390_R2_REGNUM, in);
|
|
||||||
regcache_cooked_write (regcache, S390_R3_REGNUM, in + word_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
internal_error (__FILE__, __LINE__, _("invalid return type"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RETURN_VALUE_STRUCT_CONVENTION:
|
|
||||||
error (_("Cannot set function return value."));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (out)
|
|
||||||
{
|
|
||||||
switch (rvc)
|
|
||||||
{
|
|
||||||
case RETURN_VALUE_REGISTER_CONVENTION:
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT
|
|
||||||
|| TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
|
||||||
{
|
|
||||||
/* When we store a single-precision value in an FP register,
|
|
||||||
it occupies the leftmost bits. */
|
|
||||||
regcache_cooked_read_part (regcache, S390_F0_REGNUM,
|
|
||||||
0, length, out);
|
|
||||||
}
|
|
||||||
else if (length <= word_size)
|
|
||||||
{
|
|
||||||
/* Integer arguments occupy the rightmost bits. */
|
|
||||||
regcache_cooked_read_part (regcache, S390_R2_REGNUM,
|
|
||||||
word_size - length, length, out);
|
|
||||||
}
|
|
||||||
else if (length == 2*word_size)
|
|
||||||
{
|
|
||||||
regcache_cooked_read (regcache, S390_R2_REGNUM, out);
|
|
||||||
regcache_cooked_read (regcache, S390_R3_REGNUM, out + word_size);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
internal_error (__FILE__, __LINE__, _("invalid return type"));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case RETURN_VALUE_STRUCT_CONVENTION:
|
|
||||||
error (_("Function return value unknown."));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rvc;
|
return rvc;
|
||||||
|
Reference in New Issue
Block a user