From patchwork Mon Jun 4 13:29:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 27614 Received: (qmail 17935 invoked by alias); 4 Jun 2018 13:29:16 -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 15066 invoked by uid 89); 4 Jun 2018 13:29:15 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, MIME_BASE64_BLANKS, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=v30 X-HELO: EUR01-VE1-obe.outbound.protection.outlook.com Received: from mail-ve1eur01on0042.outbound.protection.outlook.com (HELO EUR01-VE1-obe.outbound.protection.outlook.com) (104.47.1.42) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 04 Jun 2018 13:29:12 +0000 Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com (10.172.226.148) by DB6PR0802MB2165.eurprd08.prod.outlook.com (10.172.227.11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.820.13; Mon, 4 Jun 2018 13:29:08 +0000 Received: from DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::d984:bdee:1856:c64]) by DB6PR0802MB2133.eurprd08.prod.outlook.com ([fe80::d984:bdee:1856:c64%7]) with mapi id 15.20.0820.010; Mon, 4 Jun 2018 13:29:08 +0000 From: Alan Hayward To: Simon Marchi , Pedro Alves CC: "gdb-patches@sourceware.org" , nd Subject: Re: [PATCH 6/8] Aarch64 SVE pseudo register support Date: Mon, 4 Jun 2018 13:29:08 +0000 Message-ID: References: <20180511105256.27388-1-alan.hayward@arm.com> <20180511105256.27388-7-alan.hayward@arm.com> In-Reply-To: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; DB6PR0802MB2165; 7:cbAN5Q7AlcsBY6WrJiycnH6g9mPxATn462HpFJgmjfEF955pF+3ZvOQ24xQBNFUvt8RU0lkRZ/Tc0KvKwggz2tKh7gBJtNjH4kg+EAPWIscNSQejcP6PS8S+w9/D4qqketArH8Ly++Wr1yuTtsal72a85pobpLmVyPoPMsDrFKJZS7tvwn8o74EPtntfFsRwZ9C1y5lP4ZRRsAToMdYCejzWUfbIRUeWHb6I5cqwvxnEgVWSGPjDEZgXpP/SwXn7 x-ms-exchange-antispam-srfa-diagnostics: SOS; x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(48565401081)(4534165)(4627221)(201703031133081)(201702281549075)(2017052603328)(7153060)(7193020); SRVR:DB6PR0802MB2165; x-ms-traffictypediagnostic: DB6PR0802MB2165: nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(37575265505322); x-ms-exchange-senderadcheck: 1 x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(8121501046)(5005006)(93006095)(93001095)(3002001)(10201501046)(3231254)(944501410)(52105095)(6055026)(149027)(150027)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123560045)(20161123564045)(20161123562045)(20161123558120)(6072148)(201708071742011)(7699016); SRVR:DB6PR0802MB2165; BCL:0; PCL:0; RULEID:; SRVR:DB6PR0802MB2165; x-forefront-prvs: 069373DFB6 x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(366004)(396003)(39860400002)(39380400002)(376002)(346002)(189003)(199004)(26005)(3280700002)(53546011)(8676002)(59450400001)(6506007)(54906003)(76176011)(110136005)(81156014)(81166006)(72206003)(478600001)(6512007)(53936002)(6246003)(50226002)(25786009)(4326008)(8936002)(5250100002)(33656002)(5660300001)(68736007)(14454004)(106356001)(99286004)(105586002)(7736002)(66066001)(476003)(305945005)(6486002)(83716003)(229853002)(186003)(486006)(6436002)(82746002)(57306001)(2616005)(446003)(11346002)(6116002)(3846002)(3660700001)(2900100001)(102836004)(86362001)(2906002)(36756003)(316002)(97736004); DIR:OUT; SFP:1101; SCL:1; SRVR:DB6PR0802MB2165; H:DB6PR0802MB2133.eurprd08.prod.outlook.com; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; MX:1; A:1; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: gC2VpnWziRFAqIQZJS16+UbNk2+lruuB8gTX9KOpRvuewsdSwIafsCVYO5kU1gevY5YKaC341gkpl1o9TgL+a4wxh+EHuluCI5rxK1Qoozjash1wtK2j5quvVQGRtMQ/g2U7gq0J7hV9V6mVI7fX1nIFDtaJZUSiNGWIOGfN12QmLz1saeGWajgN9G2LvUPS spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: MIME-Version: 1.0 X-MS-Office365-Filtering-Correlation-Id: 254aa4f1-0a3a-447f-cd74-08d5ca1f26b6 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-Network-Message-Id: 254aa4f1-0a3a-447f-cd74-08d5ca1f26b6 X-MS-Exchange-CrossTenant-originalarrivaltime: 04 Jun 2018 13:29:08.3863 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB6PR0802MB2165 X-IsSubscribed: yes Update of patch posted below. > On 31 May 2018, at 15:57, Pedro Alves wrote: > > On 05/11/2018 11:52 AM, Alan Hayward wrote: > >> +/* Return the type for an AdvSISD V register. */ >> + >> +static struct type * >> +aarch64_vnv_type (struct gdbarch *gdbarch) >> +{ >> + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); >> + >> + if (tdep->vnv_type == NULL) >> + { >> + struct type *t; >> + struct type *elem; > > ELEM appears unused. > Leftover from copy paste of previous block of code. Removed. > On 31 May 2018, at 13:21, Simon Marchi wrote: > > On 2018-05-11 06:52 AM, Alan Hayward wrote: >> Add the functionality for reading/writing psuedo registers. > > “pseudo" Done. >> >> static struct value * >> -aarch64_pseudo_read_value_2 (readable_regcache *regcache, int regnum_offset, >> +aarch64_pseudo_read_value_2 (struct gdbarch *gdbarch, >> + readable_regcache *regcache, int regnum_offset, >> int regsize, struct value *result_value) >> { >> - gdb_byte reg_buf[V_REGISTER_SIZE]; >> + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); >> + gdb_byte v_buf[V_REGISTER_SIZE], *reg_buf; >> + gdb_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); >> unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset; >> >> + /* Enough space to read a full vector register. */ >> + if (tdep->has_sve ()) >> + reg_buf = (gdb_byte *) xmalloc (register_size (gdbarch, AARCH64_V0_REGNUM)); >> + else >> + reg_buf = v_buf; > > If the size of a register (even with SVE) will always be reasonable to allocate on the > stack, maybe you could just use > > gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)]; > > (If there is always a register with number AARCH64_V0_REGNUM, that is) > > Otherwise, it would be good to use an std::unique_ptr/gdb::unique_xmalloc_ptr to avoid > the manual xfree. > > Same in aarch64_pseudo_write_2. > Thinking about this a little more, on an SVE system, a compiler spill of a SVE register is going to result in it going to the stack anyway. Max size of an SVE register we support is 256 bytes, which doesn't seem unreasonable to add to the stack. Updated to use an array. Are you happy with the new version? Thanks, Alan. diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h index b6b9b30e715291fb0512f214a88ce49445fb290b..76243b7de53483bf8394adc1f7c493798da25b06 100644 --- a/gdb/aarch64-tdep.h +++ b/gdb/aarch64-tdep.h @@ -70,6 +70,7 @@ struct gdbarch_tdep struct type *vns_type; struct type *vnh_type; struct type *vnb_type; + struct type *vnv_type; /* syscall record. */ int (*aarch64_syscall_record) (struct regcache *regcache, unsigned long svc_number); diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c index b752338178f28a1169234a76941a1546bbc9dfa7..f04729f402ec56416cd772e5ca94f0681ea85beb 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -69,6 +69,7 @@ #define AARCH64_S0_REGNUM (AARCH64_D0_REGNUM + 32) #define AARCH64_H0_REGNUM (AARCH64_S0_REGNUM + 32) #define AARCH64_B0_REGNUM (AARCH64_H0_REGNUM + 32) +#define AARCH64_SVE_V0_REGNUM (AARCH64_B0_REGNUM + 32) /* All possible aarch64 target descriptors. */ struct target_desc *tdesc_aarch64_list[AARCH64_MAX_SVE_VQ + 1]; @@ -1766,6 +1767,30 @@ aarch64_vnb_type (struct gdbarch *gdbarch) return tdep->vnb_type; } +/* Return the type for an AdvSISD V register. */ + +static struct type * +aarch64_vnv_type (struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + if (tdep->vnv_type == NULL) + { + struct type *t = arch_composite_type (gdbarch, "__gdb_builtin_type_vnv", + TYPE_CODE_UNION); + + append_composite_type_field (t, "d", aarch64_vnd_type (gdbarch)); + append_composite_type_field (t, "s", aarch64_vns_type (gdbarch)); + append_composite_type_field (t, "h", aarch64_vnh_type (gdbarch)); + append_composite_type_field (t, "b", aarch64_vnb_type (gdbarch)); + append_composite_type_field (t, "q", aarch64_vnq_type (gdbarch)); + + tdep->vnv_type = t; + } + + return tdep->vnv_type; +} + /* Implement the "dwarf2_reg_to_regnum" gdbarch method. */ static int @@ -2114,6 +2139,8 @@ aarch64_gen_return_address (struct gdbarch *gdbarch, static const char * aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + static const char *const q_name[] = { "q0", "q1", "q2", "q3", @@ -2191,6 +2218,25 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) return b_name[regnum - AARCH64_B0_REGNUM]; + if (tdep->has_sve ()) + { + static const char *const sve_v_name[] = + { + "v0", "v1", "v2", "v3", + "v4", "v5", "v6", "v7", + "v8", "v9", "v10", "v11", + "v12", "v13", "v14", "v15", + "v16", "v17", "v18", "v19", + "v20", "v21", "v22", "v23", + "v24", "v25", "v26", "v27", + "v28", "v29", "v30", "v31", + }; + + if (regnum >= AARCH64_SVE_V0_REGNUM + && regnum < AARCH64_SVE_V0_REGNUM + AARCH64_V_REGS_NUM) + return sve_v_name[regnum - AARCH64_SVE_V0_REGNUM]; + } + internal_error (__FILE__, __LINE__, _("aarch64_pseudo_register_name: bad register number %d"), regnum); @@ -2201,6 +2247,8 @@ aarch64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) static struct type * aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + regnum -= gdbarch_num_regs (gdbarch); if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) @@ -2218,6 +2266,10 @@ aarch64_pseudo_register_type (struct gdbarch *gdbarch, int regnum) if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) return aarch64_vnb_type (gdbarch); + if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM + && regnum < AARCH64_SVE_V0_REGNUM + 32) + return aarch64_vnv_type (gdbarch); + internal_error (__FILE__, __LINE__, _("aarch64_pseudo_register_type: bad register number %d"), regnum); @@ -2229,6 +2281,8 @@ static int aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, struct reggroup *group) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + regnum -= gdbarch_num_regs (gdbarch); if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) @@ -2243,6 +2297,9 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, return group == all_reggroup || group == vector_reggroup; else if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) return group == all_reggroup || group == vector_reggroup; + else if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM + && regnum < AARCH64_SVE_V0_REGNUM + 32) + return group == all_reggroup || group == vector_reggroup; return group == all_reggroup; } @@ -2250,17 +2307,22 @@ aarch64_pseudo_register_reggroup_p (struct gdbarch *gdbarch, int regnum, /* Helper for aarch64_pseudo_read_value. */ static struct value * -aarch64_pseudo_read_value_1 (readable_regcache *regcache, int regnum_offset, +aarch64_pseudo_read_value_1 (struct gdbarch *gdbarch, + readable_regcache *regcache, int regnum_offset, int regsize, struct value *result_value) { - gdb_byte reg_buf[V_REGISTER_SIZE]; unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset; + /* Enough space for a full vector register. */ + gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)]; + gdb_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); + if (regcache->raw_read (v_regnum, reg_buf) != REG_VALID) mark_value_bytes_unavailable (result_value, 0, TYPE_LENGTH (value_type (result_value))); else memcpy (value_contents_raw (result_value), reg_buf, regsize); + return result_value; } @@ -2270,6 +2332,7 @@ static struct value * aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, int regnum) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct value *result_value = allocate_value (register_type (gdbarch, regnum)); VALUE_LVAL (result_value) = lval_register; @@ -2278,42 +2341,56 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch, readable_regcache *regcache, regnum -= gdbarch_num_regs (gdbarch); if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_Q0_REGNUM, + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_Q0_REGNUM, Q_REGISTER_SIZE, result_value); if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_D0_REGNUM, + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_D0_REGNUM, D_REGISTER_SIZE, result_value); if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_S0_REGNUM, + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_S0_REGNUM, S_REGISTER_SIZE, result_value); if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_H0_REGNUM, + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_H0_REGNUM, H_REGISTER_SIZE, result_value); if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) - return aarch64_pseudo_read_value_1 (regcache, regnum - AARCH64_B0_REGNUM, + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_B0_REGNUM, B_REGISTER_SIZE, result_value); + if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM + && regnum < AARCH64_SVE_V0_REGNUM + 32) + return aarch64_pseudo_read_value_1 (gdbarch, regcache, + regnum - AARCH64_SVE_V0_REGNUM, + V_REGISTER_SIZE, result_value); + gdb_assert_not_reached ("regnum out of bound"); } /* Helper for aarch64_pseudo_write. */ static void -aarch64_pseudo_write_1 (struct regcache *regcache, int regnum_offset, - int regsize, const gdb_byte *buf) +aarch64_pseudo_write_1 (struct gdbarch *gdbarch, struct regcache *regcache, + int regnum_offset, int regsize, const gdb_byte *buf) { - gdb_byte reg_buf[V_REGISTER_SIZE]; unsigned v_regnum = AARCH64_V0_REGNUM + regnum_offset; + /* Enough space for a full vector register. */ + gdb_byte reg_buf[register_size (gdbarch, AARCH64_V0_REGNUM)]; + gdb_assert (AARCH64_V0_REGNUM == AARCH64_SVE_Z0_REGNUM); + /* Ensure the register buffer is zero, we want gdb writes of the various 'scalar' pseudo registers to behavior like architectural writes, register width bytes are written the remainder are set to zero. */ - memset (reg_buf, 0, sizeof (reg_buf)); + memset (reg_buf, 0, register_size (gdbarch, AARCH64_V0_REGNUM)); memcpy (reg_buf, buf, regsize); regcache->raw_write (v_regnum, reg_buf); @@ -2325,27 +2402,39 @@ static void aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, const gdb_byte *buf) { + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); regnum -= gdbarch_num_regs (gdbarch); if (regnum >= AARCH64_Q0_REGNUM && regnum < AARCH64_Q0_REGNUM + 32) - return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_Q0_REGNUM, - Q_REGISTER_SIZE, buf); + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_Q0_REGNUM, Q_REGISTER_SIZE, + buf); if (regnum >= AARCH64_D0_REGNUM && regnum < AARCH64_D0_REGNUM + 32) - return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_D0_REGNUM, - D_REGISTER_SIZE, buf); + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_D0_REGNUM, D_REGISTER_SIZE, + buf); if (regnum >= AARCH64_S0_REGNUM && regnum < AARCH64_S0_REGNUM + 32) - return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_S0_REGNUM, - S_REGISTER_SIZE, buf); + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_S0_REGNUM, S_REGISTER_SIZE, + buf); if (regnum >= AARCH64_H0_REGNUM && regnum < AARCH64_H0_REGNUM + 32) - return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_H0_REGNUM, - H_REGISTER_SIZE, buf); + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_H0_REGNUM, H_REGISTER_SIZE, + buf); if (regnum >= AARCH64_B0_REGNUM && regnum < AARCH64_B0_REGNUM + 32) - return aarch64_pseudo_write_1 (regcache, regnum - AARCH64_B0_REGNUM, - B_REGISTER_SIZE, buf); + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_B0_REGNUM, B_REGISTER_SIZE, + buf); + + if (tdep->has_sve () && regnum >= AARCH64_SVE_V0_REGNUM + && regnum < AARCH64_SVE_V0_REGNUM + 32) + return aarch64_pseudo_write_1 (gdbarch, regcache, + regnum - AARCH64_SVE_V0_REGNUM, + V_REGISTER_SIZE, buf); gdb_assert_not_reached ("regnum out of bound"); }