mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-08-06 14:49:38 +08:00
Add regcache raw_supply_integer and raw_collect_integer.
Use these to replace instances of MAX_REGISTER_SIZE. * defs.h (copy_integer_to_size): New declaration. * findvar.c (copy_integer_to_size): New function. (do_cint_test): New selftest function. (copy_integer_to_size_test): Likewise. (_initialize_findvar): Likewise. * mips-fbsd-tdep.c (mips_fbsd_supply_reg): Use raw_supply_integer. (mips_fbsd_collect_reg): Use raw_collect_integer. * mips-linux-tdep.c (supply_32bit_reg): Use raw_supply_integer. (mips64_fill_gregset): Use raw_collect_integer (mips64_fill_fpregset): Use raw_supply_integer. * regcache.c (regcache::raw_supply_integer): New function. (regcache::raw_collect_integer): Likewise. * regcache.h: (regcache::raw_supply_integer): New declaration. (regcache::raw_collect_integer): Likewise.
This commit is contained in:
128
gdb/findvar.c
128
gdb/findvar.c
@ -33,6 +33,7 @@
|
||||
#include "objfiles.h"
|
||||
#include "language.h"
|
||||
#include "dwarf2loc.h"
|
||||
#include "selftest.h"
|
||||
|
||||
/* Basic byte-swapping routines. All 'extract' functions return a
|
||||
host-format integer from a target-format integer at ADDR which is
|
||||
@ -249,7 +250,46 @@ store_typed_address (gdb_byte *buf, struct type *type, CORE_ADDR addr)
|
||||
gdbarch_address_to_pointer (get_type_arch (type), type, buf, addr);
|
||||
}
|
||||
|
||||
/* Copy a value from SOURCE of size SOURCE_SIZE bytes to DEST of size DEST_SIZE
|
||||
bytes. If SOURCE_SIZE is greater than DEST_SIZE, then truncate the most
|
||||
significant bytes. If SOURCE_SIZE is less than DEST_SIZE then either sign
|
||||
or zero extended according to IS_SIGNED. Values are stored in memory with
|
||||
endianess BYTE_ORDER. */
|
||||
|
||||
void
|
||||
copy_integer_to_size (gdb_byte *dest, int dest_size, const gdb_byte *source,
|
||||
int source_size, bool is_signed,
|
||||
enum bfd_endian byte_order)
|
||||
{
|
||||
signed int size_diff = dest_size - source_size;
|
||||
|
||||
/* Copy across everything from SOURCE that can fit into DEST. */
|
||||
|
||||
if (byte_order == BFD_ENDIAN_BIG && size_diff > 0)
|
||||
memcpy (dest + size_diff, source, source_size);
|
||||
else if (byte_order == BFD_ENDIAN_BIG && size_diff < 0)
|
||||
memcpy (dest, source - size_diff, dest_size);
|
||||
else
|
||||
memcpy (dest, source, std::min (source_size, dest_size));
|
||||
|
||||
/* Fill the remaining space in DEST by either zero extending or sign
|
||||
extending. */
|
||||
|
||||
if (size_diff > 0)
|
||||
{
|
||||
gdb_byte extension = 0;
|
||||
if (is_signed
|
||||
&& ((byte_order != BFD_ENDIAN_BIG && source[source_size - 1] & 0x80)
|
||||
|| (byte_order == BFD_ENDIAN_BIG && source[0] & 0x80)))
|
||||
extension = 0xff;
|
||||
|
||||
/* Extend into MSBs of SOURCE. */
|
||||
if (byte_order == BFD_ENDIAN_BIG)
|
||||
memset (dest, extension, size_diff);
|
||||
else
|
||||
memset (dest + source_size, extension, size_diff);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a `value' with the contents of (virtual or cooked) register
|
||||
REGNUM as found in the specified FRAME. The register's type is
|
||||
@ -1005,3 +1045,91 @@ address_from_register (int regnum, struct frame_info *frame)
|
||||
return result;
|
||||
}
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
namespace selftests {
|
||||
namespace findvar_tests {
|
||||
|
||||
/* Function to test copy_integer_to_size. Store SOURCE_VAL with size
|
||||
SOURCE_SIZE to a buffer, making sure no sign extending happens at this
|
||||
stage. Copy buffer to a new buffer using copy_integer_to_size. Extract
|
||||
copied value and compare to DEST_VALU. Copy again with a signed
|
||||
copy_integer_to_size and compare to DEST_VALS. Do everything for both
|
||||
LITTLE and BIG target endians. Use unsigned values throughout to make
|
||||
sure there are no implicit sign extensions. */
|
||||
|
||||
static void
|
||||
do_cint_test (ULONGEST dest_valu, ULONGEST dest_vals, int dest_size,
|
||||
ULONGEST src_val, int src_size)
|
||||
{
|
||||
for (int i = 0; i < 2 ; i++)
|
||||
{
|
||||
gdb_byte srcbuf[sizeof (ULONGEST)] = {};
|
||||
gdb_byte destbuf[sizeof (ULONGEST)] = {};
|
||||
enum bfd_endian byte_order = i ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
|
||||
|
||||
/* Fill the src buffer (and later the dest buffer) with non-zero junk,
|
||||
to ensure zero extensions aren't hidden. */
|
||||
memset (srcbuf, 0xaa, sizeof (srcbuf));
|
||||
|
||||
/* Store (and later extract) using unsigned to ensure there are no sign
|
||||
extensions. */
|
||||
store_unsigned_integer (srcbuf, src_size, byte_order, src_val);
|
||||
|
||||
/* Test unsigned. */
|
||||
memset (destbuf, 0xaa, sizeof (destbuf));
|
||||
copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, false,
|
||||
byte_order);
|
||||
SELF_CHECK (dest_valu == extract_unsigned_integer (destbuf, dest_size,
|
||||
byte_order));
|
||||
|
||||
/* Test signed. */
|
||||
memset (destbuf, 0xaa, sizeof (destbuf));
|
||||
copy_integer_to_size (destbuf, dest_size, srcbuf, src_size, true,
|
||||
byte_order);
|
||||
SELF_CHECK (dest_vals == extract_unsigned_integer (destbuf, dest_size,
|
||||
byte_order));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
copy_integer_to_size_test ()
|
||||
{
|
||||
/* Destination is bigger than the source, which has the signed bit unset. */
|
||||
do_cint_test (0x12345678, 0x12345678, 8, 0x12345678, 4);
|
||||
do_cint_test (0x345678, 0x345678, 8, 0x12345678, 3);
|
||||
|
||||
/* Destination is bigger than the source, which has the signed bit set. */
|
||||
do_cint_test (0xdeadbeef, 0xffffffffdeadbeef, 8, 0xdeadbeef, 4);
|
||||
do_cint_test (0xadbeef, 0xffffffffffadbeef, 8, 0xdeadbeef, 3);
|
||||
|
||||
/* Destination is smaller than the source. */
|
||||
do_cint_test (0x5678, 0x5678, 2, 0x12345678, 3);
|
||||
do_cint_test (0xbeef, 0xbeef, 2, 0xdeadbeef, 3);
|
||||
|
||||
/* Destination and source are the same size. */
|
||||
do_cint_test (0x8765432112345678, 0x8765432112345678, 8, 0x8765432112345678,
|
||||
8);
|
||||
do_cint_test (0x432112345678, 0x432112345678, 6, 0x8765432112345678, 6);
|
||||
do_cint_test (0xfeedbeaddeadbeef, 0xfeedbeaddeadbeef, 8, 0xfeedbeaddeadbeef,
|
||||
8);
|
||||
do_cint_test (0xbeaddeadbeef, 0xbeaddeadbeef, 6, 0xfeedbeaddeadbeef, 6);
|
||||
|
||||
/* Destination is bigger than the source. Source is bigger than 32bits. */
|
||||
do_cint_test (0x3412345678, 0x3412345678, 8, 0x3412345678, 6);
|
||||
do_cint_test (0xff12345678, 0xff12345678, 8, 0xff12345678, 6);
|
||||
do_cint_test (0x432112345678, 0x432112345678, 8, 0x8765432112345678, 6);
|
||||
do_cint_test (0xff2112345678, 0xffffff2112345678, 8, 0xffffff2112345678, 6);
|
||||
}
|
||||
|
||||
} // namespace findvar_test
|
||||
} // namespace selftests
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
_initialize_findvar (void)
|
||||
{
|
||||
#if GDB_SELF_TEST
|
||||
register_self_test (selftests::findvar_tests::copy_integer_to_size_test);
|
||||
#endif
|
||||
}
|
||||
|
Reference in New Issue
Block a user