|
|
0b42f8 |
commit 4e65a17e62c7c2f3c0409d9769cca2e916a88379
|
|
|
0b42f8 |
Author: Andreas Arnez <arnez@linux.vnet.ibm.com>
|
|
|
0b42f8 |
Date: Mon Apr 27 11:38:47 2015 +0200
|
|
|
0b42f8 |
|
|
|
0b42f8 |
S390: Re-arrange implementation of s390_return_value
|
|
|
0b42f8 |
|
|
|
0b42f8 |
Move related logic in the implementation of s390_return_value closer
|
|
|
0b42f8 |
together. This makes it easier to read and extend.
|
|
|
0b42f8 |
|
|
|
0b42f8 |
gdb/ChangeLog:
|
|
|
0b42f8 |
|
|
|
0b42f8 |
* s390-linux-tdep.c (s390_return_value_convention): Remove
|
|
|
0b42f8 |
function. Inline its logic...
|
|
|
0b42f8 |
(s390_return_value): ...here. Instead, move the handling of the
|
|
|
0b42f8 |
"register" return value convention...
|
|
|
0b42f8 |
(s390_register_return_value): ...here. New function.
|
|
|
0b42f8 |
|
|
|
0b42f8 |
### a/gdb/ChangeLog
|
|
|
0b42f8 |
### b/gdb/ChangeLog
|
|
|
0b42f8 |
## -1,5 +1,13 @@
|
|
|
0b42f8 |
2015-04-27 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
|
|
0b42f8 |
|
|
|
0b42f8 |
+ * s390-linux-tdep.c (s390_return_value_convention): Remove
|
|
|
0b42f8 |
+ function. Inline its logic...
|
|
|
0b42f8 |
+ (s390_return_value): ...here. Instead, move the handling of the
|
|
|
0b42f8 |
+ "register" return value convention...
|
|
|
0b42f8 |
+ (s390_register_return_value): ...here. New function.
|
|
|
0b42f8 |
+
|
|
|
0b42f8 |
+2015-04-27 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
|
|
0b42f8 |
+
|
|
|
0b42f8 |
* s390-linux-tdep.c
|
|
|
0b42f8 |
(is_float_singleton): Remove function. Move the "singleton" part
|
|
|
0b42f8 |
of the logic...
|
|
|
0b42f8 |
Index: gdb-7.6.1/gdb/s390-tdep.c
|
|
|
0b42f8 |
===================================================================
|
|
|
0b42f8 |
--- gdb-7.6.1.orig/gdb/s390-tdep.c 2016-02-21 22:31:47.311935241 +0100
|
|
|
0b42f8 |
+++ gdb-7.6.1/gdb/s390-tdep.c 2016-02-21 22:31:59.326029901 +0100
|
|
|
0b42f8 |
@@ -2865,110 +2865,98 @@
|
|
|
0b42f8 |
}
|
|
|
0b42f8 |
|
|
|
0b42f8 |
|
|
|
0b42f8 |
-/* Function return value access. */
|
|
|
0b42f8 |
+/* Helper for s390_return_value: Set or retrieve a function return
|
|
|
0b42f8 |
+ value if it resides in a register. */
|
|
|
0b42f8 |
|
|
|
0b42f8 |
-static enum return_value_convention
|
|
|
0b42f8 |
-s390_return_value_convention (struct gdbarch *gdbarch, struct type *type)
|
|
|
0b42f8 |
+static void
|
|
|
0b42f8 |
+s390_register_return_value (struct gdbarch *gdbarch, struct type *type,
|
|
|
0b42f8 |
+ struct regcache *regcache,
|
|
|
0b42f8 |
+ gdb_byte *out, const gdb_byte *in)
|
|
|
0b42f8 |
{
|
|
|
0b42f8 |
- if (TYPE_LENGTH (type) > 8)
|
|
|
0b42f8 |
- return RETURN_VALUE_STRUCT_CONVENTION;
|
|
|
0b42f8 |
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
0b42f8 |
+ int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
|
|
0b42f8 |
+ int length = TYPE_LENGTH (type);
|
|
|
0b42f8 |
+ int code = TYPE_CODE (type);
|
|
|
0b42f8 |
|
|
|
0b42f8 |
- switch (TYPE_CODE (type))
|
|
|
0b42f8 |
+ if (code == TYPE_CODE_FLT || code == TYPE_CODE_DECFLOAT)
|
|
|
0b42f8 |
{
|
|
|
0b42f8 |
- case TYPE_CODE_STRUCT:
|
|
|
0b42f8 |
- case TYPE_CODE_UNION:
|
|
|
0b42f8 |
- case TYPE_CODE_ARRAY:
|
|
|
0b42f8 |
- case TYPE_CODE_COMPLEX:
|
|
|
0b42f8 |
- return RETURN_VALUE_STRUCT_CONVENTION;
|
|
|
0b42f8 |
-
|
|
|
0b42f8 |
- default:
|
|
|
0b42f8 |
- return RETURN_VALUE_REGISTER_CONVENTION;
|
|
|
0b42f8 |
+ /* Float-like value: left-aligned in f0. */
|
|
|
0b42f8 |
+ if (in != NULL)
|
|
|
0b42f8 |
+ regcache_cooked_write_part (regcache, S390_F0_REGNUM,
|
|
|
0b42f8 |
+ 0, length, in);
|
|
|
0b42f8 |
+ else
|
|
|
0b42f8 |
+ regcache_cooked_read_part (regcache, S390_F0_REGNUM,
|
|
|
0b42f8 |
+ 0, length, out);
|
|
|
0b42f8 |
+ }
|
|
|
0b42f8 |
+ else if (length <= word_size)
|
|
|
0b42f8 |
+ {
|
|
|
0b42f8 |
+ /* Integer: zero- or sign-extended in r2. */
|
|
|
0b42f8 |
+ if (out != NULL)
|
|
|
0b42f8 |
+ regcache_cooked_read_part (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
+ word_size - length, length, out);
|
|
|
0b42f8 |
+ else if (TYPE_UNSIGNED (type))
|
|
|
0b42f8 |
+ regcache_cooked_write_unsigned
|
|
|
0b42f8 |
+ (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
+ extract_unsigned_integer (in, length, byte_order));
|
|
|
0b42f8 |
+ else
|
|
|
0b42f8 |
+ regcache_cooked_write_signed
|
|
|
0b42f8 |
+ (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
+ extract_signed_integer (in, length, byte_order));
|
|
|
0b42f8 |
}
|
|
|
0b42f8 |
+ else if (length == 2 * word_size)
|
|
|
0b42f8 |
+ {
|
|
|
0b42f8 |
+ /* Double word: in r2 and r3. */
|
|
|
0b42f8 |
+ if (in != NULL)
|
|
|
0b42f8 |
+ {
|
|
|
0b42f8 |
+ regcache_cooked_write (regcache, S390_R2_REGNUM, in);
|
|
|
0b42f8 |
+ regcache_cooked_write (regcache, S390_R3_REGNUM,
|
|
|
0b42f8 |
+ in + word_size);
|
|
|
0b42f8 |
+ }
|
|
|
0b42f8 |
+ else
|
|
|
0b42f8 |
+ {
|
|
|
0b42f8 |
+ regcache_cooked_read (regcache, S390_R2_REGNUM, out);
|
|
|
0b42f8 |
+ regcache_cooked_read (regcache, S390_R3_REGNUM,
|
|
|
0b42f8 |
+ out + word_size);
|
|
|
0b42f8 |
+ }
|
|
|
0b42f8 |
+ }
|
|
|
0b42f8 |
+ else
|
|
|
0b42f8 |
+ internal_error (__FILE__, __LINE__, _("invalid return type"));
|
|
|
0b42f8 |
}
|
|
|
0b42f8 |
|
|
|
0b42f8 |
+
|
|
|
0b42f8 |
+/* Implement the 'return_value' gdbarch method. */
|
|
|
0b42f8 |
+
|
|
|
0b42f8 |
static enum return_value_convention
|
|
|
0b42f8 |
s390_return_value (struct gdbarch *gdbarch, struct value *function,
|
|
|
0b42f8 |
struct type *type, struct regcache *regcache,
|
|
|
0b42f8 |
gdb_byte *out, const gdb_byte *in)
|
|
|
0b42f8 |
{
|
|
|
0b42f8 |
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
|
|
0b42f8 |
- int word_size = gdbarch_ptr_bit (gdbarch) / 8;
|
|
|
0b42f8 |
enum return_value_convention rvc;
|
|
|
0b42f8 |
- int length;
|
|
|
0b42f8 |
|
|
|
0b42f8 |
type = check_typedef (type);
|
|
|
0b42f8 |
- rvc = s390_return_value_convention (gdbarch, type);
|
|
|
0b42f8 |
- length = TYPE_LENGTH (type);
|
|
|
0b42f8 |
|
|
|
0b42f8 |
- if (in)
|
|
|
0b42f8 |
+ switch (TYPE_CODE (type))
|
|
|
0b42f8 |
{
|
|
|
0b42f8 |
- switch (rvc)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- case RETURN_VALUE_REGISTER_CONVENTION:
|
|
|
0b42f8 |
- if (TYPE_CODE (type) == TYPE_CODE_FLT
|
|
|
0b42f8 |
- || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- /* When we store a single-precision value in an FP register,
|
|
|
0b42f8 |
- it occupies the leftmost bits. */
|
|
|
0b42f8 |
- regcache_cooked_write_part (regcache, S390_F0_REGNUM,
|
|
|
0b42f8 |
- 0, length, in);
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else if (length <= word_size)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- /* Integer arguments are always extended to word size. */
|
|
|
0b42f8 |
- if (TYPE_UNSIGNED (type))
|
|
|
0b42f8 |
- regcache_cooked_write_unsigned (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
- extract_unsigned_integer (in, length, byte_order));
|
|
|
0b42f8 |
- else
|
|
|
0b42f8 |
- regcache_cooked_write_signed (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
- extract_signed_integer (in, length, byte_order));
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else if (length == 2*word_size)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- regcache_cooked_write (regcache, S390_R2_REGNUM, in);
|
|
|
0b42f8 |
- regcache_cooked_write (regcache, S390_R3_REGNUM, in + word_size);
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else
|
|
|
0b42f8 |
- internal_error (__FILE__, __LINE__, _("invalid return type"));
|
|
|
0b42f8 |
- break;
|
|
|
0b42f8 |
-
|
|
|
0b42f8 |
- case RETURN_VALUE_STRUCT_CONVENTION:
|
|
|
0b42f8 |
- error (_("Cannot set function return value."));
|
|
|
0b42f8 |
- break;
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
+ case TYPE_CODE_STRUCT:
|
|
|
0b42f8 |
+ case TYPE_CODE_UNION:
|
|
|
0b42f8 |
+ case TYPE_CODE_ARRAY:
|
|
|
0b42f8 |
+ case TYPE_CODE_COMPLEX:
|
|
|
0b42f8 |
+ rvc = RETURN_VALUE_STRUCT_CONVENTION;
|
|
|
0b42f8 |
+ break;
|
|
|
0b42f8 |
+ default:
|
|
|
0b42f8 |
+ rvc = TYPE_LENGTH (type) <= 8
|
|
|
0b42f8 |
+ ? RETURN_VALUE_REGISTER_CONVENTION
|
|
|
0b42f8 |
+ : RETURN_VALUE_STRUCT_CONVENTION;
|
|
|
0b42f8 |
}
|
|
|
0b42f8 |
- else if (out)
|
|
|
0b42f8 |
+
|
|
|
0b42f8 |
+ if (in != NULL || out != NULL)
|
|
|
0b42f8 |
{
|
|
|
0b42f8 |
- switch (rvc)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- case RETURN_VALUE_REGISTER_CONVENTION:
|
|
|
0b42f8 |
- if (TYPE_CODE (type) == TYPE_CODE_FLT
|
|
|
0b42f8 |
- || TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- /* When we store a single-precision value in an FP register,
|
|
|
0b42f8 |
- it occupies the leftmost bits. */
|
|
|
0b42f8 |
- regcache_cooked_read_part (regcache, S390_F0_REGNUM,
|
|
|
0b42f8 |
- 0, length, out);
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else if (length <= word_size)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- /* Integer arguments occupy the rightmost bits. */
|
|
|
0b42f8 |
- regcache_cooked_read_part (regcache, S390_R2_REGNUM,
|
|
|
0b42f8 |
- word_size - length, length, out);
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else if (length == 2*word_size)
|
|
|
0b42f8 |
- {
|
|
|
0b42f8 |
- regcache_cooked_read (regcache, S390_R2_REGNUM, out);
|
|
|
0b42f8 |
- regcache_cooked_read (regcache, S390_R3_REGNUM, out + word_size);
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
- else
|
|
|
0b42f8 |
- internal_error (__FILE__, __LINE__, _("invalid return type"));
|
|
|
0b42f8 |
- break;
|
|
|
0b42f8 |
-
|
|
|
0b42f8 |
- case RETURN_VALUE_STRUCT_CONVENTION:
|
|
|
0b42f8 |
- error (_("Function return value unknown."));
|
|
|
0b42f8 |
- break;
|
|
|
0b42f8 |
- }
|
|
|
0b42f8 |
+ if (rvc == RETURN_VALUE_REGISTER_CONVENTION)
|
|
|
0b42f8 |
+ s390_register_return_value (gdbarch, type, regcache, out, in);
|
|
|
0b42f8 |
+ else if (in != NULL)
|
|
|
0b42f8 |
+ error (_("Cannot set function return value."));
|
|
|
0b42f8 |
+ else
|
|
|
0b42f8 |
+ error (_("Function return value unknown."));
|
|
|
0b42f8 |
}
|
|
|
0b42f8 |
|
|
|
0b42f8 |
return rvc;
|