regcache: Add functions suitable for regset_supply/collect.
These functions are intended to suit all targets that don't require too special logic in their regset supply/collect methods. Having such generic functions helps reducing target-specific complexity.
This commit is contained in:
parent
7fefa8d7d6
commit
0b3092721e
3 changed files with 141 additions and 0 deletions
|
@ -1,3 +1,12 @@
|
|||
2014-08-07 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||
|
||||
* regcache.c: Include "regset.h".
|
||||
(regcache_transfer_regset): New local function.
|
||||
(regcache_supply_regset, regcache_collect_regset): New functions.
|
||||
* regcache.h (struct regcache_map_entry): New structure.
|
||||
(REGCACHE_MAP_SKIP): New enum value.
|
||||
(regcache_supply_regset, regcache_collect_regset): New prototypes.
|
||||
|
||||
2014-08-07 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||
|
||||
* regset.h (struct regset): Rename 'descr' field to 'regmap'.
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "exceptions.h"
|
||||
#include "remote.h"
|
||||
#include "valprint.h"
|
||||
#include "regset.h"
|
||||
|
||||
/*
|
||||
* DATA STRUCTURE
|
||||
|
@ -1066,6 +1067,92 @@ regcache_raw_collect (const struct regcache *regcache, int regnum, void *buf)
|
|||
memcpy (buf, regbuf, size);
|
||||
}
|
||||
|
||||
/* Transfer a single or all registers belonging to a certain register
|
||||
set to or from a buffer. This is the main worker function for
|
||||
regcache_supply_regset and regcache_collect_regset. */
|
||||
|
||||
static void
|
||||
regcache_transfer_regset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
struct regcache *out_regcache,
|
||||
int regnum, const void *in_buf,
|
||||
void *out_buf, size_t size)
|
||||
{
|
||||
const struct regcache_map_entry *map;
|
||||
int offs = 0, count;
|
||||
|
||||
for (map = regset->regmap; (count = map->count) != 0; map++)
|
||||
{
|
||||
int regno = map->regno;
|
||||
int slot_size = map->size;
|
||||
|
||||
if (slot_size == 0 && regno != REGCACHE_MAP_SKIP)
|
||||
slot_size = regcache->descr->sizeof_register[regno];
|
||||
|
||||
if (regno == REGCACHE_MAP_SKIP
|
||||
|| (regnum != -1
|
||||
&& (regnum < regno || regnum >= regno + count)))
|
||||
offs += count * slot_size;
|
||||
|
||||
else if (regnum == -1)
|
||||
for (; count--; regno++, offs += slot_size)
|
||||
{
|
||||
if (offs + slot_size > size)
|
||||
break;
|
||||
|
||||
if (out_buf)
|
||||
regcache_raw_collect (regcache, regno,
|
||||
(gdb_byte *) out_buf + offs);
|
||||
else
|
||||
regcache_raw_supply (out_regcache, regno, in_buf
|
||||
? (const gdb_byte *) in_buf + offs
|
||||
: NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer a single register and return. */
|
||||
offs += (regnum - regno) * slot_size;
|
||||
if (offs + slot_size > size)
|
||||
return;
|
||||
|
||||
if (out_buf)
|
||||
regcache_raw_collect (regcache, regnum,
|
||||
(gdb_byte *) out_buf + offs);
|
||||
else
|
||||
regcache_raw_supply (out_regcache, regnum, in_buf
|
||||
? (const gdb_byte *) in_buf + offs
|
||||
: NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Supply register REGNUM from BUF to REGCACHE, using the register map
|
||||
in REGSET. If REGNUM is -1, do this for all registers in REGSET.
|
||||
If BUF is NULL, set the register(s) to "unavailable" status. */
|
||||
|
||||
void
|
||||
regcache_supply_regset (const struct regset *regset,
|
||||
struct regcache *regcache,
|
||||
int regnum, const void *buf, size_t size)
|
||||
{
|
||||
regcache_transfer_regset (regset, regcache, regcache, regnum,
|
||||
buf, NULL, size);
|
||||
}
|
||||
|
||||
/* Collect register REGNUM from REGCACHE to BUF, using the register
|
||||
map in REGSET. If REGNUM is -1, do this for all registers in
|
||||
REGSET. */
|
||||
|
||||
void
|
||||
regcache_collect_regset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *buf, size_t size)
|
||||
{
|
||||
regcache_transfer_regset (regset, regcache, NULL, regnum,
|
||||
NULL, buf, size);
|
||||
}
|
||||
|
||||
|
||||
/* Special handling for register PC. */
|
||||
|
||||
|
|
|
@ -147,6 +147,51 @@ extern void regcache_raw_supply (struct regcache *regcache,
|
|||
extern void regcache_raw_collect (const struct regcache *regcache,
|
||||
int regnum, void *buf);
|
||||
|
||||
/* Mapping between register numbers and offsets in a buffer, for use
|
||||
in the '*regset' functions below. In an array of
|
||||
'regcache_map_entry' each element is interpreted like follows:
|
||||
|
||||
- If 'regno' is a register number: Map register 'regno' to the
|
||||
current offset (starting with 0) and increase the current offset
|
||||
by 'size' (or the register's size, if 'size' is zero). Repeat
|
||||
this with consecutive register numbers up to 'regno+count-1'.
|
||||
|
||||
- If 'regno' is REGCACHE_MAP_SKIP: Add 'count*size' to the current
|
||||
offset.
|
||||
|
||||
- If count=0: End of the map. */
|
||||
|
||||
struct regcache_map_entry
|
||||
{
|
||||
int count;
|
||||
int regno;
|
||||
int size;
|
||||
};
|
||||
|
||||
/* Special value for the 'regno' field in the struct above. */
|
||||
|
||||
enum
|
||||
{
|
||||
REGCACHE_MAP_SKIP = -1,
|
||||
};
|
||||
|
||||
/* Transfer a set of registers (as described by REGSET) between
|
||||
REGCACHE and BUF. If REGNUM == -1, transfer all registers
|
||||
belonging to the regset, otherwise just the register numbered
|
||||
REGNUM. The REGSET's 'regmap' field must point to an array of
|
||||
'struct regcache_map_entry'.
|
||||
|
||||
These functions are suitable for the 'regset_supply' and
|
||||
'regset_collect' fields in a regset structure. */
|
||||
|
||||
extern void regcache_supply_regset (const struct regset *regset,
|
||||
struct regcache *regcache,
|
||||
int regnum, const void *buf,
|
||||
size_t size);
|
||||
extern void regcache_collect_regset (const struct regset *regset,
|
||||
const struct regcache *regcache,
|
||||
int regnum, void *buf, size_t size);
|
||||
|
||||
|
||||
/* The type of a register. This function is slightly more efficient
|
||||
then its gdbarch vector counterpart since it returns a precomputed
|
||||
|
|
Loading…
Add table
Reference in a new issue