Make gdb aware of the return values of functions which
return in registers.
gdb/ChangeLog:
* s12z-tdep.c (s12z_extract_return_value): New function.
(inv_reg_perm) New array.
(s12z_return_value): Populate readbuf if non-null.
---
gdb/s12z-tdep.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 61 insertions(+), 1 deletion(-)
diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c
index bd0bd7c001..3da88523f7 100644
--- a/gdb/s12z-tdep.c
+++ b/gdb/s12z-tdep.c
@@ -37,7 +37,9 @@
#define N_PHYSICAL_REGISTERS (S12Z_N_REGISTERS - 2)
-/* A permutation of all the physical registers. */
+/* A permutation of all the physical registers. Indexing this array
+ with an integer from gdb's internal representation will return the
+ register enum. */
static const int reg_perm[N_PHYSICAL_REGISTERS] =
{
REG_D0,
@@ -55,6 +57,16 @@ static const int reg_perm[N_PHYSICAL_REGISTERS] =
REG_CCW
};
+/* The inverse of the above permutation. Indexing this
+ array with a register enum (e.g. REG_D2) will return the register
+ number in gdb's internal representation. */
+static const int inv_reg_perm[N_PHYSICAL_REGISTERS] =
+ {
+ 2, 3, 4, 5, /* d2, d3, d4, d5 */
+ 0, 1, /* d0, d1 */
+ 6, 7, /* d6, d7 */
+ 8, 9, 10, 11, 12 /* x, y, s, p, ccw */
+ };
/* Return the name of the register REGNUM. */
static const char *
@@ -467,11 +479,59 @@ s12z_print_registers_info (struct gdbarch *gdbarch,
+
+static void
+s12z_extract_return_value (struct type *type, struct regcache *regcache,
+ void *valbuf)
+{
+ int reg = -1;
+
+ gdb_byte buf[4];
+
+ switch (TYPE_LENGTH (type))
+ {
+ case 0: /* Nothing to do */
+ return;
+
+ case 1:
+ reg = REG_D0;
+ break;
+
+ case 2:
+ reg = REG_D2;
+ break;
+
+ case 3:
+ reg = REG_X;
+ break;
+
+ case 4:
+ reg = REG_D6;
+ break;
+
+ default:
+ error (_("bad size for return value"));
+ return;
+ }
+
+ regcache->cooked_read (inv_reg_perm[reg], buf);
+ memcpy (valbuf, buf, TYPE_LENGTH (type));
+}
+
static enum return_value_convention
s12z_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT
+ || TYPE_CODE (type) == TYPE_CODE_UNION
+ || TYPE_CODE (type) == TYPE_CODE_ARRAY
+ || TYPE_LENGTH (type) > 4)
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ if (readbuf)
+ s12z_extract_return_value (type, regcache, readbuf);
+
return RETURN_VALUE_REGISTER_CONVENTION;
}
--
2.11.0