From patchwork Tue May 23 17:49:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 20546 Received: (qmail 102572 invoked by alias); 23 May 2017 17:49:44 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 102526 invoked by uid 89); 23 May 2017 17:49:43 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LOTSOFHASH, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=mock, Hx-spam-relays-external:15.01.1101.021, H*RU:15.01.1101.021, HX-HELO:sk:EUR01-V X-HELO: EUR01-VE1-obe.outbound.protection.outlook.com Received: from mail-ve1eur01on0064.outbound.protection.outlook.com (HELO EUR01-VE1-obe.outbound.protection.outlook.com) (104.47.1.64) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 23 May 2017 17:49:39 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com (10.160.211.19) by AM3PR08MB0102.eurprd08.prod.outlook.com (10.160.211.20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256) id 15.1.1124.9; Tue, 23 May 2017 17:49:37 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::b823:64c1:afc5:3a08]) by AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::b823:64c1:afc5:3a08%17]) with mapi id 15.01.1101.021; Tue, 23 May 2017 17:49:37 +0000 From: Alan Hayward To: Pedro Alves CC: Yao Qi , "gdb-patches@sourceware.org" , nd Subject: Re: [PATCH 3/11] Add MIPS_MAX_REGISTER_SIZE (2/4) Date: Tue, 23 May 2017 17:49:37 +0000 Message-ID: <4F90CD36-759D-4BDA-BFEC-8DD86F44A0B7@arm.com> References: <3C00280E-37C9-4C0A-9DA6-F3B9DB1A6E8F@arm.com> <86y3v7uf9j.fsf@gmail.com> <806B436F-EFA1-4200-AC54-9036D166C9B9@arm.com> <867f1m8nhm.fsf@gmail.com> <8637bx9jsw.fsf@gmail.com> <78A7E8EA-7203-44DF-B7FD-63E75A5ECEF5@arm.com> <540372d8-efc3-f842-5cac-cd813bacc3f5@redhat.com> In-Reply-To: <540372d8-efc3-f842-5cac-cd813bacc3f5@redhat.com> authentication-results: redhat.com; dkim=none (message not signed) header.d=none; redhat.com; dmarc=none action=none header.from=arm.com; x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; AM3PR08MB0102; 7:1BmlS2Y0zWzoCmfQxbgxp5JiaenPkHD6KPiQiUAhyUB3ENc7CGaqLzsyh4y5QYk3XpWUE+U98vl68BfqyhhZH/gQGV7X43q+mPn6YBzLyl//JDDrdt3ESzn2eIvMc9N0L6jf1nlZksGgbMUzk1t3A4H99j7vjxaVNr+WIep/edjfrtmMek/hoW3YhmXikuYeOEtZEbax6HVR35NvIhIBGKT3zJbZmn7k2v8EE++NqTZSeNXqiG1OjqQ1U3fc6rWo/e+8LZjylpSxg403YN+KkCOYk4vLDlsErZXDnI7gejS1r6PssenctvFOE9exRmiaYPxDAs/UGQhCotgsKTWteg== x-ms-traffictypediagnostic: AM3PR08MB0102: x-ms-office365-filtering-correlation-id: 74d52e9b-9441-41d2-5a36-08d4a20414c3 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(2017030254075)(48565401081)(201703131423075)(201703031133081)(201702281549075); SRVR:AM3PR08MB0102; nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(180628864354917); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6040450)(601004)(2401047)(5005006)(8121501046)(3002001)(93006095)(93001095)(10201501046)(6055026)(6041248)(20161123564025)(20161123562025)(20161123558100)(20161123560025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(6072148); SRVR:AM3PR08MB0102; BCL:0; PCL:0; RULEID:; SRVR:AM3PR08MB0102; x-forefront-prvs: 0316567485 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(6009001)(39410400002)(39860400002)(39840400002)(39400400002)(39450400003)(39850400002)(377454003)(24454002)(377424004)(6116002)(102836003)(3846002)(110136004)(6436002)(33656002)(575784001)(6246003)(86362001)(4326008)(76176999)(38730400002)(50986999)(54356999)(53546009)(5250100002)(25786009)(6916009)(81166006)(2950100002)(5660300001)(93886004)(8676002)(66066001)(229853002)(6486002)(2900100001)(6506006)(189998001)(8936002)(7736002)(305945005)(3660700001)(72206003)(53936002)(3280700002)(83716003)(478600001)(53946003)(2906002)(39060400002)(36756003)(6512007)(99286003)(82746002)(54906002)(579004); DIR:OUT; SFP:1101; SCL:1; SRVR:AM3PR08MB0102; H:AM3PR08MB0101.eurprd08.prod.outlook.com; FPR:; SPF:None; MLV:ovrnspm; PTR:InfoNoRecords; LANG:en; spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <68923E451CDF524D91E609EAC8522A7F@eurprd08.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-originalarrivaltime: 23 May 2017 17:49:37.4075 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM3PR08MB0102 > On 22 May 2017, at 18:15, Pedro Alves wrote: > > On 05/22/2017 05:05 PM, Alan Hayward wrote: > >> { >> enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); >> - gdb_byte buf[MAX_REGISTER_SIZE]; >> LONGEST val; >> >> - val = extract_signed_integer ((const gdb_byte *) addr, len, byte_order); >> - store_signed_integer (buf, register_size (gdbarch, regnum), byte_order, >> - val); >> - regcache_raw_supply (regcache, regnum, buf); >> + val = extract_integer ((const gdb_byte *) addr, len, byte_order); >> + regcache->raw_supply (regnum, val); >> } >> } >> > >> else >> { >> enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); >> - gdb_byte buf[MAX_REGISTER_SIZE]; >> - LONGEST val; >> - >> - regcache_raw_collect (regcache, regnum, buf); >> - val = extract_signed_integer (buf, register_size (gdbarch, regnum), >> - byte_order); >> - store_signed_integer ((gdb_byte *) addr, len, byte_order, val); >> + LONGEST val = regcache->raw_collect (regnum); >> + store_integer ((gdb_byte *) addr, len, byte_order, val); > > I wonder whether we can get rid of the LONGEST / host integer > middleman and simplify things while at it. For instance, what if we > had a version of raw_collect that took the destination buffer length > as parameter: > > regcache->raw_collect_integer (regnum, (gdb_byte *) addr, len); > > that would copy bytes over into addr, and if the register is > narrower than LEN, then it'd insert the necessary > leading zeros (or 0xFFs if signed extension necessary), > and if the registers is wider than LEN, then it'd skip > copying enough significant bytes so that LEN fits. > > Likewise for regcache->raw_supply. Is it the case that gdb always does a store_integer after a raw_collect of a (U)LONGEST? And always an extract_integer before a raw_supply of a (U)LONGEST ? (Both of these are tricky to grep for, because the code sequence is over multiple lines) I was going to mock up a new raw_collect_integer, but then got carried away and wrote the full patch changes. This version makes the MIPS files look neater. > > >> --- a/gdb/regcache.h >> +++ b/gdb/regcache.h >> @@ -21,6 +21,7 @@ >> #define REGCACHE_H >> >> #include "common-regcache.h" >> +#include "defs.h" > > Headers should not include defs.h. Is there some .c file that > misses including defs.h first thing? > I think I needed it in an earlier version of my patch. Removed. New version with raw_collect_integer and raw_supply_integer. Tested on a --enable-targets=all build using make check with board files unix and native-gdbserver. I do not have a MIPS machine to test on. Ok to commit? Alan. 2017-05-23 Alan Hayward * gdb/defs.h (LongType): New templated type. (extract_integer): New declaration. (extract_signed_integer): Switched to inline. (extract_unsigned_integer): Likewise. (store_integer): New declaration (store_signed_integer): Switched to inline. (store_unsigned_integer): Likewise. * gdb/findvar.c (extract_signed_integer): Removed function. (extract_unsigned_integer): Likewise. (store_signed_integer): Removed function. (store_unsigned_integer): Likewise. * mips-fbsd-tdep.c (mips_fbsd_supply_reg): Use raw_supply_integer. (mips_fbsd_collect_reg): Use templated 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. * gdb/regcache.c (regcache::raw_supply_integer): New function and instantiations. (regcache::raw_collect_integer): Likewise * gdb/regcache.h (regcache::raw_supply): New declaration. (regcache::raw_collect): Likewise diff --git a/gdb/defs.h b/gdb/defs.h index a0b586f401eca205334e9f237081f4da97c83aa1..010fe55a4760ebc7a420115e7590199fcab899a0 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -627,6 +627,11 @@ enum symbol_needs_kind SYMBOL_NEEDS_FRAME }; +template +using LongType = typename std::enable_if<(std::is_same::value + || std::is_same::value), + T>::type; + /* Dynamic target-system-dependent parameters for GDB. */ #include "gdbarch.h" @@ -637,11 +642,69 @@ enum { MAX_REGISTER_SIZE = 64 }; /* In findvar.c. */ -extern LONGEST extract_signed_integer (const gdb_byte *, int, - enum bfd_endian); +/* All 'extract' functions return a host-format integer from a target-format + integer at ADDR which is LEN bytes long. */ -extern ULONGEST extract_unsigned_integer (const gdb_byte *, int, - enum bfd_endian); +template +LongType +extract_integer (const gdb_byte *addr, int len, enum bfd_endian byte_order) +{ + T retval = 0; + const unsigned char *p; + const unsigned char *startaddr = addr; + const unsigned char *endaddr = startaddr + len; + + if (len > (int) sizeof (T)) + error (_("\ +That operation is not available on integers of more than %d bytes."), + (int) sizeof (T)); + + /* Start at the most significant end of the integer, and work towards + the least significant. */ + if (byte_order == BFD_ENDIAN_BIG) + { + p = startaddr; + if (std::is_signed::value) + { + /* Do the sign extension once at the start. */ + retval = ((LONGEST) * p ^ 0x80) - 0x80; + ++p; + } + for (; p < endaddr; ++p) + retval = (retval << 8) | *p; + } + else + { + p = endaddr - 1; + if (std::is_signed::value) + { + /* Do the sign extension once at the start. */ + retval = ((LONGEST) * p ^ 0x80) - 0x80; + --p; + } + for (; p >= startaddr; --p) + retval = (retval << 8) | *p; + } + return retval; +} + +template LongType extract_integer + (const gdb_byte *addr, int len, enum bfd_endian byte_order); + +template LongType extract_integer + (const gdb_byte *addr, int len, enum bfd_endian byte_order); + +inline ULONGEST extract_unsigned_integer (const gdb_byte *addr, int len, + enum bfd_endian byte_order) +{ + return extract_integer (addr, len, byte_order); +} + +inline LONGEST extract_signed_integer (const gdb_byte *addr, int len, + enum bfd_endian byte_order) +{ + return extract_integer (addr, len, byte_order); +} extern int extract_long_unsigned_integer (const gdb_byte *, int, enum bfd_endian, LONGEST *); @@ -649,11 +712,58 @@ extern int extract_long_unsigned_integer (const gdb_byte *, int, extern CORE_ADDR extract_typed_address (const gdb_byte *buf, struct type *type); -extern void store_signed_integer (gdb_byte *, int, - enum bfd_endian, LONGEST); +/* All 'store' functions accept a host-format integer and store a + target-format integer at ADDR which is LEN bytes long. */ -extern void store_unsigned_integer (gdb_byte *, int, - enum bfd_endian, ULONGEST); +template +typename std::enable_if<(std::is_same::value + || std::is_same::value), + void>::type +store_integer (gdb_byte *addr, int len, enum bfd_endian byte_order, + T val) +{ + gdb_byte *p; + gdb_byte *startaddr = addr; + gdb_byte *endaddr = startaddr + len; + + /* Start at the least significant end of the integer, and work towards + the most significant. */ + if (byte_order == BFD_ENDIAN_BIG) + { + for (p = endaddr - 1; p >= startaddr; --p) + { + *p = val & 0xff; + val >>= 8; + } + } + else + { + for (p = startaddr; p < endaddr; ++p) + { + *p = val & 0xff; + val >>= 8; + } + } +} + +template void store_integer (gdb_byte *addr, int len, + enum bfd_endian byte_order, + LongType val); +template void store_integer (gdb_byte *addr, int len, + enum bfd_endian byte_order, + LongType val); + +inline void store_signed_integer (gdb_byte *addr, int len, + enum bfd_endian byte_order, LONGEST val) +{ + store_integer (addr, len, byte_order, val); +} + +inline void store_unsigned_integer (gdb_byte *addr, int len, + enum bfd_endian byte_order, ULONGEST val) +{ + store_integer (addr, len, byte_order, val); +} extern void store_typed_address (gdb_byte *buf, struct type *type, CORE_ADDR addr); diff --git a/gdb/findvar.c b/gdb/findvar.c index ed4d5c1266c9de069981b306bc8229ae5fb02350..614d1291eac5a7438a1bf3f6dd0b5d012a0dfaa7 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -34,9 +34,7 @@ #include "language.h" #include "dwarf2loc.h" -/* Basic byte-swapping routines. All 'extract' functions return a - host-format integer from a target-format integer at ADDR which is - LEN bytes long. */ +/* Basic byte-swapping routines. */ #if TARGET_CHAR_BIT != 8 || HOST_CHAR_BIT != 8 /* 8 bit characters are a pretty safe assumption these days, so we @@ -46,70 +44,6 @@ you lose #endif -LONGEST -extract_signed_integer (const gdb_byte *addr, int len, - enum bfd_endian byte_order) -{ - LONGEST retval; - const unsigned char *p; - const unsigned char *startaddr = addr; - const unsigned char *endaddr = startaddr + len; - - if (len > (int) sizeof (LONGEST)) - error (_("\ -That operation is not available on integers of more than %d bytes."), - (int) sizeof (LONGEST)); - - /* Start at the most significant end of the integer, and work towards - the least significant. */ - if (byte_order == BFD_ENDIAN_BIG) - { - p = startaddr; - /* Do the sign extension once at the start. */ - retval = ((LONGEST) * p ^ 0x80) - 0x80; - for (++p; p < endaddr; ++p) - retval = (retval << 8) | *p; - } - else - { - p = endaddr - 1; - /* Do the sign extension once at the start. */ - retval = ((LONGEST) * p ^ 0x80) - 0x80; - for (--p; p >= startaddr; --p) - retval = (retval << 8) | *p; - } - return retval; -} - -ULONGEST -extract_unsigned_integer (const gdb_byte *addr, int len, - enum bfd_endian byte_order) -{ - ULONGEST retval; - const unsigned char *p; - const unsigned char *startaddr = addr; - const unsigned char *endaddr = startaddr + len; - - if (len > (int) sizeof (ULONGEST)) - error (_("\ -That operation is not available on integers of more than %d bytes."), - (int) sizeof (ULONGEST)); - - /* Start at the most significant end of the integer, and work towards - the least significant. */ - retval = 0; - if (byte_order == BFD_ENDIAN_BIG) - { - for (p = startaddr; p < endaddr; ++p) - retval = (retval << 8) | *p; - } - else - { - for (p = endaddr - 1; p >= startaddr; --p) - retval = (retval << 8) | *p; - } - return retval; -} /* Sometimes a long long unsigned integer can be extracted as a LONGEST value. This is done so that we can print these values @@ -177,65 +111,6 @@ extract_typed_address (const gdb_byte *buf, struct type *type) return gdbarch_pointer_to_address (get_type_arch (type), type, buf); } -/* All 'store' functions accept a host-format integer and store a - target-format integer at ADDR which is LEN bytes long. */ - -void -store_signed_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, LONGEST val) -{ - gdb_byte *p; - gdb_byte *startaddr = addr; - gdb_byte *endaddr = startaddr + len; - - /* Start at the least significant end of the integer, and work towards - the most significant. */ - if (byte_order == BFD_ENDIAN_BIG) - { - for (p = endaddr - 1; p >= startaddr; --p) - { - *p = val & 0xff; - val >>= 8; - } - } - else - { - for (p = startaddr; p < endaddr; ++p) - { - *p = val & 0xff; - val >>= 8; - } - } -} - -void -store_unsigned_integer (gdb_byte *addr, int len, - enum bfd_endian byte_order, ULONGEST val) -{ - unsigned char *p; - unsigned char *startaddr = (unsigned char *) addr; - unsigned char *endaddr = startaddr + len; - - /* Start at the least significant end of the integer, and work towards - the most significant. */ - if (byte_order == BFD_ENDIAN_BIG) - { - for (p = endaddr - 1; p >= startaddr; --p) - { - *p = val & 0xff; - val >>= 8; - } - } - else - { - for (p = startaddr; p < endaddr; ++p) - { - *p = val & 0xff; - val >>= 8; - } - } -} - /* Store the address ADDR as a pointer of type TYPE at BUF, in target form. */ void diff --git a/gdb/mips-fbsd-tdep.c b/gdb/mips-fbsd-tdep.c index 00fae0ec60ddc9e645d3236efe29f2f9e9ceab5c..7278fb71e3ad1f18d35cd696832d99bf90198620 100644 --- a/gdb/mips-fbsd-tdep.c +++ b/gdb/mips-fbsd-tdep.c @@ -48,9 +48,8 @@ #define MIPS_FBSD_NUM_FPREGS 34 /* Supply a single register. If the source register size matches the - size the regcache expects, this can use regcache_raw_supply(). If - they are different, this copies the source register into a buffer - that can be passed to regcache_raw_supply(). */ + size the regcache expects, this can use regcache->raw_supply (). If + they are different, this can use regcache->raw_supply_integer (). */ static void mips_fbsd_supply_reg (struct regcache *regcache, int regnum, const void *addr, @@ -59,25 +58,16 @@ mips_fbsd_supply_reg (struct regcache *regcache, int regnum, const void *addr, struct gdbarch *gdbarch = get_regcache_arch (regcache); if (register_size (gdbarch, regnum) == len) - regcache_raw_supply (regcache, regnum, addr); + regcache->raw_supply (regnum, addr); else - { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - val = extract_signed_integer ((const gdb_byte *) addr, len, byte_order); - store_signed_integer (buf, register_size (gdbarch, regnum), byte_order, - val); - regcache_raw_supply (regcache, regnum, buf); - } + regcache->raw_supply_integer (regnum, (const gdb_byte *) addr, + len); } /* Collect a single register. If the destination register size matches the size the regcache expects, this can use - regcache_raw_supply(). If they are different, this fetches the - register via regcache_raw_supply() into a buffer and then copies it - into the final destination. */ + regcache->raw_collect (). If they are different, this can use + regcache->raw_collect_integer (). */ static void mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr, @@ -86,18 +76,9 @@ mips_fbsd_collect_reg (const struct regcache *regcache, int regnum, void *addr, struct gdbarch *gdbarch = get_regcache_arch (regcache); if (register_size (gdbarch, regnum) == len) - regcache_raw_collect (regcache, regnum, addr); + regcache->raw_collect (regnum, addr); else - { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regnum, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regnum), - byte_order); - store_signed_integer ((gdb_byte *) addr, len, byte_order, val); - } + regcache->raw_collect_integer (regnum, (gdb_byte *) addr, len); } /* Supply the floating-point registers stored in FPREGS to REGCACHE. diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 48a582a16c934abe6e8f87c46a6009649c606d49..b30fe294a0bbbb815418e65149a88f59eb15befb 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -116,13 +116,7 @@ mips_linux_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) static void supply_32bit_reg (struct regcache *regcache, int regnum, const void *addr) { - struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - gdb_byte buf[MAX_REGISTER_SIZE]; - store_signed_integer (buf, register_size (gdbarch, regnum), byte_order, - extract_signed_integer ((const gdb_byte *) addr, 4, - byte_order)); - regcache_raw_supply (regcache, regnum, buf); + regcache->raw_supply_integer (regnum, (const gdb_byte *) addr, 4); } /* Unpack an elf_gregset_t into GDB's register cache. */ @@ -417,7 +411,6 @@ mips64_fill_gregset (const struct regcache *regcache, mips64_elf_gregset_t *gregsetp, int regno) { struct gdbarch *gdbarch = get_regcache_arch (regcache); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int regaddr, regi; mips64_elf_greg_t *regp = *gregsetp; void *dst; @@ -460,14 +453,8 @@ mips64_fill_gregset (const struct regcache *regcache, if (regaddr != -1) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); dst = regp + regaddr; - store_signed_integer ((gdb_byte *) dst, 8, byte_order, val); + regcache->raw_collect_integer (regno, (gdb_byte *) dst, 8); } } @@ -564,25 +551,13 @@ mips64_fill_fpregset (const struct regcache *regcache, } else if (regno == mips_regnum (gdbarch)->fp_control_status) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); to = (gdb_byte *) (*fpregsetp + 32); - store_signed_integer (to, 4, byte_order, val); + regcache->raw_collect_integer (regno, to, 4); } else if (regno == mips_regnum (gdbarch)->fp_implementation_revision) { - gdb_byte buf[MAX_REGISTER_SIZE]; - LONGEST val; - - regcache_raw_collect (regcache, regno, buf); - val = extract_signed_integer (buf, register_size (gdbarch, regno), - byte_order); to = (gdb_byte *) (*fpregsetp + 32) + 4; - store_signed_integer (to, 4, byte_order, val); + regcache->raw_collect_integer (regno, to, 4); } else if (regno == -1) { diff --git a/gdb/regcache.h b/gdb/regcache.h index 4dcfccbac70f0f962bf5e5596d035fda42322795..c47401948270b1c75d9d3b02cbbc3256db85f84e 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -294,8 +294,20 @@ public: void raw_collect (int regnum, void *buf) const; + template + typename std::enable_if<(std::is_same::value + || std::is_same::value), + void>::type + raw_collect_integer (int regnum, gdb_byte *addr, int addr_len) const; + void raw_supply (int regnum, const void *buf); + template + typename std::enable_if<(std::is_same::value + || std::is_same::value), + void>::type + raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len); + void raw_supply_zeroed (int regnum); void raw_copy (int regnum, struct regcache *src_regcache); diff --git a/gdb/regcache.c b/gdb/regcache.c index 660558f7ff10f9d8346b6e08422e16c38c3c4d7d..cc9ab74b087cbda2d79264674e9b463e1528363f 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -1189,6 +1189,39 @@ regcache::raw_supply (int regnum, const void *buf) } } +/* Supply register REGNUM, whose contents are stored in ADDR, with length + ADDR_LEN to a (U)LONGEST, then store to REGCACHE, taking BYTE_ORDER into + account. */ + +template +typename std::enable_if<(std::is_same::value + || std::is_same::value), + void>::type +regcache::raw_supply_integer (int regnum, const gdb_byte *addr, int addr_len) +{ + enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); + gdb_byte *regbuf; + size_t regsize; + T val; + + gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers); + gdb_assert (!m_readonly_p); + + regbuf = register_buffer (regnum); + regsize = m_descr->sizeof_register[regnum]; + + val = extract_integer (addr, addr_len, byte_order); + store_integer (regbuf, regsize, byte_order, val); + m_register_status[regnum] = REG_VALID; +} + +template void regcache::raw_supply_integer (int regnum, + const gdb_byte *addr, + int addr_len); +template void regcache::raw_supply_integer (int regnum, + const gdb_byte *addr, + int addr_len); + /* Supply register REGNUM with zeroed value to REGCACHE. This is not the same as calling raw_supply with NULL (which will set the state to unavailable). */ @@ -1232,6 +1265,37 @@ regcache::raw_collect (int regnum, void *buf) const memcpy (buf, regbuf, size); } +/* Collect register REGNUM from REGCACHE into a (U)LONGEST, then store ADDR_LEN + bytes into buffer ADDR, taking BYTE_ORDER into account. */ + +template +typename std::enable_if<(std::is_same::value + || std::is_same::value), + void>::type +regcache::raw_collect_integer (int regnum, gdb_byte *addr, int addr_len) const +{ + enum bfd_endian byte_order = gdbarch_byte_order (m_descr->gdbarch); + const gdb_byte *regbuf; + size_t regsize; + T val; + + gdb_assert (regnum >= 0 && regnum < m_descr->nr_raw_registers); + + regbuf = register_buffer (regnum); + regsize = m_descr->sizeof_register[regnum]; + + val = extract_integer (regbuf, regsize, byte_order); + store_integer (addr, addr_len, byte_order, val); +} + +template void regcache::raw_collect_integer (int regnum, + gdb_byte *addr, + int addr_len) const; +template void regcache::raw_collect_integer (int regnum, + gdb_byte *addr, + int addr_len) const; + + void regcache::raw_copy (int regnum, struct regcache *src_regcache) {