aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Darrington <john@darrington.wattle.id.au>2018-11-20 18:50:30 +0100
committerJohn Darrington <john@darrington.wattle.id.au>2018-11-20 18:55:02 +0100
commitc3247a98cd2bf9dfcf733e6968273cce90850807 (patch)
tree02896fbafd7960dab824ece94c2733c1f8637b97
parent2fa1b3191e449f1efca31a654920a6bd3a1f4f28 (diff)
downloadgdb-c3247a98cd2bf9dfcf733e6968273cce90850807.zip
gdb-c3247a98cd2bf9dfcf733e6968273cce90850807.tar.gz
gdb-c3247a98cd2bf9dfcf733e6968273cce90850807.tar.bz2
GDB: S12Z: new function s12z_extract_return_value
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.
-rw-r--r--gdb/ChangeLog6
-rw-r--r--gdb/s12z-tdep.c59
2 files changed, 64 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 2b577d5..29b03a7 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2018-11209 John Darrington <john@darrington.wattle.id.au>
+
+ * s12z-tdep.c (s12z_extract_return_value): New function.
+ (inv_reg_perm) New array.
+ (s12z_return_value): Populate readbuf if non-null.
+
2018-11-20 Eli Zaretskii <eliz@gnu.org>
* common/filestuff.c (gdb_fopen_cloexec): Disable use of "e" mode
diff --git a/gdb/s12z-tdep.c b/gdb/s12z-tdep.c
index bd0bd7c..b358b2f 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,56 @@ s12z_print_registers_info (struct gdbarch *gdbarch,
+
+static void
+s12z_extract_return_value (struct type *type, struct regcache *regcache,
+ void *valbuf)
+{
+ int reg = -1;
+
+ 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], (gdb_byte *) valbuf);
+}
+
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;
}