From patchwork Thu Jan 25 08:32:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hui Li X-Patchwork-Id: 84717 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EF56A3858003 for ; Thu, 25 Jan 2024 08:33:25 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 09BA33858C53 for ; Thu, 25 Jan 2024 08:32:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 09BA33858C53 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 09BA33858C53 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706171568; cv=none; b=IPxJV4txcI7BGkUyx5THDi65BZ5C7X7vDHCWHK5YX32RCvbQTONvgfWov12LLFDcbfoYPJssugtUxTeIsgP9g9R3ZPU4vY+WY74CscpUawOMDGrrcDEko2R0fQEWiBfzmcIzjNXePzHrpT1qAkR0wwMztaYjvhUnNQkfkLJRtXA= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706171568; c=relaxed/simple; bh=FdHZf9l0nuZtDNLor/uv/IOyFdXQH2BL42T+1iGen40=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=q6J9123XCXovYmrrIPgv/36IhxaN6Dc20N+IfzcxqCEScFxTtHBK/TumFG4/tLuOVh8ZOwPZMLN1BbAZBOsjaYd5QX7xoHyabQvzCFCevPQmcZ+x8RxVaXrK5tkcuaZP882ogVa4nbMjJc1hNf11SCFSZIj+axU5wkmghqFKCGU= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8Dx_7uoHLJl_XYFAA--.987S3; Thu, 25 Jan 2024 16:32:40 +0800 (CST) Received: from localhost.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxXs2kHLJllgwZAA--.40368S3; Thu, 25 Jan 2024 16:32:37 +0800 (CST) From: Hui Li To: gdb-patches@sourceware.org, Tiezhu Yang Subject: [PATCH 1/2] gdb: LoongArch: Add vector extensions support Date: Thu, 25 Jan 2024 16:32:35 +0800 Message-Id: <20240125083236.28557-2-lihui@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240125083236.28557-1-lihui@loongson.cn> References: <20240125083236.28557-1-lihui@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxXs2kHLJllgwZAA--.40368S3 X-CM-SenderInfo: 5olk3xo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfZr1fAr18XF48Cr1kWw47KFX_yoW5trWfZo ZY9F4Yq3W8GFWxAF1Iqwn8Ja4vqr45CrZ3ZayUWasxCa1fCFZ8J3Wjqw13XFySqw4kGry8 urWxJ3srXFZrZr4fl-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYT7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI 0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VACjcxG62k0Y48FwI0_Jr0_Gr1lYx0E2Ix0 cI8IcVAFwI0_Jrv_JF1lYx0Ex4A2jsIE14v26r4UJVWxJr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4U MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67 AKxVWUXVWUAwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0 cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z2 80aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVWUJVW8JbIYCTnIWIevJa73UjIF yTuYvjxU7s2-UUUUU X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Add LoongArch's vector extensions support, which including 128bit LSX (i.e., Loongson SIMD eXtension) and 256bit LASX (i.e., Loongson Advanced SIMD eXtension). This patch support gdb to fetch/store vector registers. Signed-off-by: Hui Li --- gdb/arch/loongarch.c | 6 ++ gdb/arch/loongarch.h | 4 + gdb/features/Makefile | 2 + gdb/features/loongarch/lasx.c | 85 ++++++++++++++++++++ gdb/features/loongarch/lasx.xml | 60 ++++++++++++++ gdb/features/loongarch/lsx.c | 82 +++++++++++++++++++ gdb/features/loongarch/lsx.xml | 59 ++++++++++++++ gdb/loongarch-linux-nat.c | 123 +++++++++++++++++++++++++++++ gdb/loongarch-linux-tdep.c | 130 +++++++++++++++++++++++++++++++ gdb/loongarch-tdep.c | 36 +++++++++ gdb/loongarch-tdep.h | 2 + gdbserver/linux-loongarch-low.cc | 52 +++++++++++++ 12 files changed, 641 insertions(+) create mode 100644 gdb/features/loongarch/lasx.c create mode 100644 gdb/features/loongarch/lasx.xml create mode 100644 gdb/features/loongarch/lsx.c create mode 100644 gdb/features/loongarch/lsx.xml diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c index d1a7bad4d58..e9995c9fe0f 100644 --- a/gdb/arch/loongarch.c +++ b/gdb/arch/loongarch.c @@ -25,6 +25,8 @@ #include "../features/loongarch/base32.c" #include "../features/loongarch/base64.c" #include "../features/loongarch/fpu.c" +#include "../features/loongarch/lsx.c" +#include "../features/loongarch/lasx.c" #ifndef GDBSERVER #define STATIC_IN_GDB static @@ -63,6 +65,10 @@ loongarch_create_target_description (const struct loongarch_gdbarch_features fea /* For now we only support creating single float and double float. */ regnum = create_feature_loongarch_fpu (tdesc.get (), regnum); + /* For now we only support creating lsx and lasx. */ + regnum = create_feature_loongarch_lsx (tdesc.get (), regnum); + regnum = create_feature_loongarch_lasx (tdesc.get (), regnum); + return tdesc; } diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h index 1fe75d016de..d166f9d5eb9 100644 --- a/gdb/arch/loongarch.h +++ b/gdb/arch/loongarch.h @@ -41,6 +41,10 @@ enum loongarch_regnum LOONGARCH_FIRST_FCC_REGNUM = LOONGARCH_FIRST_FP_REGNUM + LOONGARCH_LINUX_NUM_FPREGSET, LOONGARCH_LINUX_NUM_FCC = 8, LOONGARCH_FCSR_REGNUM = LOONGARCH_FIRST_FCC_REGNUM + LOONGARCH_LINUX_NUM_FCC, + LOONGARCH_FIRST_LSX_REGNUM = LOONGARCH_FCSR_REGNUM + 1, + LOONGARCH_LINUX_NUM_LSXREGSET = 32, + LOONGARCH_FIRST_LASX_REGNUM = LOONGARCH_FIRST_LSX_REGNUM + LOONGARCH_LINUX_NUM_LSXREGSET, + LOONGARCH_LINUX_NUM_LASXREGSET = 32, }; enum loongarch_fputype diff --git a/gdb/features/Makefile b/gdb/features/Makefile index cda6a49d563..7c33c093375 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -237,6 +237,8 @@ FEATURE_XMLFILES = aarch64-core.xml \ loongarch/base32.xml \ loongarch/base64.xml \ loongarch/fpu.xml \ + loongarch/lsx.xml \ + loongarch/lasx.xml \ riscv/rv32e-xregs.xml \ riscv/32bit-cpu.xml \ riscv/32bit-fpu.xml \ diff --git a/gdb/features/loongarch/lasx.c b/gdb/features/loongarch/lasx.c new file mode 100644 index 00000000000..52d486ecb09 --- /dev/null +++ b/gdb/features/loongarch/lasx.c @@ -0,0 +1,85 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: lasx.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_loongarch_lasx (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lasx"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v8f32", element_type, 8); + + element_type = tdesc_named_type (feature, "ieee_double"); + tdesc_create_vector (feature, "v4f64", element_type, 4); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v32i8", element_type, 32); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v16i16", element_type, 16); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v8i32", element_type, 8); + + element_type = tdesc_named_type (feature, "int64"); + tdesc_create_vector (feature, "v4i64", element_type, 4); + + element_type = tdesc_named_type (feature, "uint128"); + tdesc_create_vector (feature, "v2ui128", element_type, 2); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "lasxv"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "v8f32"); + tdesc_add_field (type_with_fields, "v8_float", field_type); + field_type = tdesc_named_type (feature, "v4f64"); + tdesc_add_field (type_with_fields, "v4_double", field_type); + field_type = tdesc_named_type (feature, "v32i8"); + tdesc_add_field (type_with_fields, "v32_int8", field_type); + field_type = tdesc_named_type (feature, "v16i16"); + tdesc_add_field (type_with_fields, "v16_int16", field_type); + field_type = tdesc_named_type (feature, "v8i32"); + tdesc_add_field (type_with_fields, "v8_int32", field_type); + field_type = tdesc_named_type (feature, "v4i64"); + tdesc_add_field (type_with_fields, "v4_int64", field_type); + field_type = tdesc_named_type (feature, "v2ui128"); + tdesc_add_field (type_with_fields, "v2_uint128", field_type); + + tdesc_create_reg (feature, "xr0", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr1", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr2", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr3", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr4", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr5", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr6", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr7", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr8", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr9", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr10", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr11", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr12", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr13", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr14", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr15", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr16", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr17", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr18", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr19", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr20", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr21", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr22", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr23", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr24", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr25", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr26", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr27", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr28", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr29", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr30", regnum++, 1, "lasx", 256, "lasxv"); + tdesc_create_reg (feature, "xr31", regnum++, 1, "lasx", 256, "lasxv"); + return regnum; +} diff --git a/gdb/features/loongarch/lasx.xml b/gdb/features/loongarch/lasx.xml new file mode 100644 index 00000000000..753b982c651 --- /dev/null +++ b/gdb/features/loongarch/lasx.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/features/loongarch/lsx.c b/gdb/features/loongarch/lsx.c new file mode 100644 index 00000000000..0067c2fe385 --- /dev/null +++ b/gdb/features/loongarch/lsx.c @@ -0,0 +1,82 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: lsx.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_loongarch_lsx (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lsx"); + tdesc_type *element_type; + element_type = tdesc_named_type (feature, "ieee_single"); + tdesc_create_vector (feature, "v4f32", element_type, 4); + + element_type = tdesc_named_type (feature, "ieee_double"); + tdesc_create_vector (feature, "v2f64", element_type, 2); + + element_type = tdesc_named_type (feature, "int8"); + tdesc_create_vector (feature, "v16i8", element_type, 16); + + element_type = tdesc_named_type (feature, "int16"); + tdesc_create_vector (feature, "v8i16", element_type, 8); + + element_type = tdesc_named_type (feature, "int32"); + tdesc_create_vector (feature, "v4i32", element_type, 4); + + element_type = tdesc_named_type (feature, "int64"); + tdesc_create_vector (feature, "v2i64", element_type, 2); + + tdesc_type_with_fields *type_with_fields; + type_with_fields = tdesc_create_union (feature, "lsxv"); + tdesc_type *field_type; + field_type = tdesc_named_type (feature, "v4f32"); + tdesc_add_field (type_with_fields, "v4_float", field_type); + field_type = tdesc_named_type (feature, "v2f64"); + tdesc_add_field (type_with_fields, "v2_double", field_type); + field_type = tdesc_named_type (feature, "v16i8"); + tdesc_add_field (type_with_fields, "v16_int8", field_type); + field_type = tdesc_named_type (feature, "v8i16"); + tdesc_add_field (type_with_fields, "v8_int16", field_type); + field_type = tdesc_named_type (feature, "v4i32"); + tdesc_add_field (type_with_fields, "v4_int32", field_type); + field_type = tdesc_named_type (feature, "v2i64"); + tdesc_add_field (type_with_fields, "v2_int64", field_type); + field_type = tdesc_named_type (feature, "uint128"); + tdesc_add_field (type_with_fields, "uint128", field_type); + + tdesc_create_reg (feature, "vr0", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr1", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr2", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr3", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr4", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr5", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr6", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr7", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr8", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr9", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr10", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr11", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr12", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr13", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr14", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr15", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr16", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr17", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr18", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr19", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr20", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr21", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr22", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr23", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr24", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr25", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr26", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr27", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr28", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr29", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr30", regnum++, 1, "lsx", 128, "lsxv"); + tdesc_create_reg (feature, "vr31", regnum++, 1, "lsx", 128, "lsxv"); + return regnum; +} diff --git a/gdb/features/loongarch/lsx.xml b/gdb/features/loongarch/lsx.xml new file mode 100644 index 00000000000..e19a404dfd5 --- /dev/null +++ b/gdb/features/loongarch/lsx.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c index fe65b5dfa30..85d0a9619c0 100644 --- a/gdb/loongarch-linux-nat.c +++ b/gdb/loongarch-linux-nat.c @@ -146,6 +146,125 @@ store_fpregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) } } +/* Fill GDB's register array with the Loongson SIMD Extension + register values from the current thread. */ + +static void +fetch_lsxregs_from_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lsxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + { + /* If kernel dose not support lsx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + loongarch_lsxregset.supply_regset (nullptr, regcache, -1, + ®set, sizeof (regset)); + } +} + +/* Store to the current thread the valid Loongson SIMD Extension + register values in the GDB's register array. */ + +static void +store_lsxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lsxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + { + /* If kernel dose not support lsx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + { + loongarch_lsxregset.collect_regset (nullptr, regcache, regnum, + ®set, sizeof (regset)); + if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LSX, (long) &iovec) < 0) + perror_with_name (_("Couldn't set NT_LARCH_LSX registers")); + } + } +} + +/* Fill GDB's register array with the Loongson Advanced SIMD Extension + register values from the current thread. */ + +static void +fetch_lasxregs_from_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lasxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + { + /* If kernel dose not support lasx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + loongarch_lasxregset.supply_regset (nullptr, regcache, -1, + ®set, sizeof (regset)); + } +} + +/* Store to the current thread the valid Loongson Advanced SIMD Extension + register values in the GDB's register array. */ + +static void +store_lasxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + elf_lasxregset_t regset; + + if ((regnum == -1) + || (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET)) + { + struct iovec iovec = { .iov_base = ®set, .iov_len = sizeof (regset) }; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + { + /* If kernel dose not support lasx, just return. */ + if (errno == EINVAL) + return; + + perror_with_name (_("Couldn't get NT_LARCH_LSX registers")); + } + else + { + loongarch_lasxregset.collect_regset (nullptr, regcache, regnum, + ®set, sizeof (regset)); + if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LASX, (long) &iovec) < 0) + perror_with_name (_("Couldn't set NT_LARCH_LASX registers")); + } + } +} + + /* Implement the "fetch_registers" target_ops method. */ void @@ -156,6 +275,8 @@ loongarch_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_gregs_from_thread(regcache, regnum, tid); fetch_fpregs_from_thread(regcache, regnum, tid); + fetch_lsxregs_from_thread(regcache, regnum, tid); + fetch_lasxregs_from_thread(regcache, regnum, tid); } /* Implement the "store_registers" target_ops method. */ @@ -168,6 +289,8 @@ loongarch_linux_nat_target::store_registers (struct regcache *regcache, store_gregs_to_thread (regcache, regnum, tid); store_fpregs_to_thread(regcache, regnum, tid); + store_lsxregs_to_thread(regcache, regnum, tid); + store_lasxregs_to_thread(regcache, regnum, tid); } /* Return the address in the core dump or inferior of register REGNO. */ diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c index 47f36a18931..726b6716270 100644 --- a/gdb/loongarch-linux-tdep.c +++ b/gdb/loongarch-linux-tdep.c @@ -215,6 +215,129 @@ const struct regset loongarch_fpregset = loongarch_fill_fpregset, }; +/* Unpack elf_lsxregset_t into GDB's register cache. */ + +static void +loongarch_supply_lsxregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *lsxrs, size_t len) +{ + int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); + const gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + { + buf = (const gdb_byte*) lsxrs + lsxrsize * i; + regcache->raw_supply (LOONGARCH_FIRST_LSX_REGNUM + i, (const void *) buf); + } + + } + else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) + { + buf = (const gdb_byte*) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); + regcache->raw_supply (regnum, (const void *) buf); + } +} + +/* Pack the GDB's register cache value into an elf_lsxregset_t. */ + +static void +loongarch_fill_lsxregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *lsxrs, size_t len) +{ + int lsxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LSX_REGNUM); + gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + { + buf = (gdb_byte *) lsxrs + lsxrsize * i; + regcache->raw_collect (LOONGARCH_FIRST_LSX_REGNUM + i, (void *) buf); + } + } + else if (regnum >= LOONGARCH_FIRST_LSX_REGNUM && regnum < LOONGARCH_FIRST_LASX_REGNUM) + { + buf = (gdb_byte *) lsxrs + lsxrsize * (regnum - LOONGARCH_FIRST_LSX_REGNUM); + regcache->raw_collect (regnum, (void *) buf); + } +} + +/* Define the Loongson SIMD Extension register regset. */ + +const struct regset loongarch_lsxregset = +{ + nullptr, + loongarch_supply_lsxregset, + loongarch_fill_lsxregset, +}; + +/* Unpack elf_lasxregset_t into GDB's register cache. */ + +static void +loongarch_supply_lasxregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *lasxrs, size_t len) +{ + int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); + const gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + { + buf = (const gdb_byte*) lasxrs + lasxrsize * i; + regcache->raw_supply (LOONGARCH_FIRST_LASX_REGNUM + i, (const void *) buf); + } + + } + else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + { + buf = (const gdb_byte*) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); + regcache->raw_supply (regnum, (const void *) buf); + } +} + +/* Pack the GDB's register cache value into an elf_lasxregset_t. */ + +static void +loongarch_fill_lasxregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *lasxrs, size_t len) +{ + int lasxrsize = register_size (regcache->arch (), LOONGARCH_FIRST_LASX_REGNUM); + gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + { + buf = (gdb_byte *) lasxrs + lasxrsize * i; + regcache->raw_collect (LOONGARCH_FIRST_LASX_REGNUM + i, (void *) buf); + } + } + else if (regnum >= LOONGARCH_FIRST_LASX_REGNUM + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + + { + buf = (gdb_byte *) lasxrs + lasxrsize * (regnum - LOONGARCH_FIRST_LASX_REGNUM); + regcache->raw_collect (regnum, (void *) buf); + } +} + +/* Define the Loongson Advanced SIMD Extension register regset. */ + +const struct regset loongarch_lasxregset = +{ + nullptr, + loongarch_supply_lasxregset, + loongarch_fill_lasxregset, +}; + /* Implement the "init" method of struct tramp_frame. */ #define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128 @@ -269,10 +392,17 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch, int fcsrsize = register_size (gdbarch, LOONGARCH_FCSR_REGNUM); int fpsize = fprsize * LOONGARCH_LINUX_NUM_FPREGSET + fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize; + int lsxrsize = register_size (gdbarch, LOONGARCH_FIRST_LSX_REGNUM); + int lasxrsize = register_size (gdbarch, LOONGARCH_FIRST_LASX_REGNUM); cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize, LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data); cb (".reg2", fpsize, fpsize, &loongarch_fpregset, nullptr, cb_data); + cb (".reg-loongarch-lsx", lsxrsize, lsxrsize, + &loongarch_lsxregset, nullptr, cb_data); + cb (".reg-loongarch-lasx", lasxrsize, lasxrsize, + &loongarch_lasxregset, nullptr, cb_data); + } /* The following value is derived from __NR_rt_sigreturn in diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index 6d1df8599eb..f56e80f15b8 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -1650,6 +1650,14 @@ loongarch_register_reggroup_p (struct gdbarch *gdbarch, int regnum, if (group == float_reggroup) return 0; + if (LOONGARCH_FIRST_LSX_REGNUM <= regnum + && regnum < LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET) + return group == vector_reggroup; + + /* Only $vrx / $xrx in vector_reggroup */ + if (group == vector_reggroup) + return 0; + int ret = tdesc_register_in_reggroup_p (gdbarch, regnum, group); if (ret != -1) return ret; @@ -1707,6 +1715,34 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (!valid_p) return nullptr; + const struct tdesc_feature *feature_lsx + = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lsx"); + if (feature_lsx == nullptr) + return nullptr; + + /* Validate the description provides the lsx registers and + allocate their numbers. */ + regnum = LOONGARCH_FIRST_LSX_REGNUM; + for (int i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + valid_p &= tdesc_numbered_register (feature_lsx, tdesc_data.get (), regnum++, + loongarch_v_normal_name[i] + 1); + if (!valid_p) + return nullptr; + + const struct tdesc_feature *feature_lasx + = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lasx"); + if (feature_lasx == nullptr) + return nullptr; + + /* Validate the description provides the lasx registers and + allocate their numbers. */ + regnum = LOONGARCH_FIRST_LASX_REGNUM; + for (int i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + valid_p &= tdesc_numbered_register (feature_lasx, tdesc_data.get (), regnum++, + loongarch_x_normal_name[i] + 1); + if (!valid_p) + return nullptr; + /* LoongArch code is always little-endian. */ info.byte_order_for_code = BFD_ENDIAN_LITTLE; diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h index 06ce2bc3640..6e0e798e6c8 100644 --- a/gdb/loongarch-tdep.h +++ b/gdb/loongarch-tdep.h @@ -30,6 +30,8 @@ /* Register set definitions. */ extern const struct regset loongarch_gregset; extern const struct regset loongarch_fpregset; +extern const struct regset loongarch_lsxregset; +extern const struct regset loongarch_lasxregset; /* Target-dependent structure in gdbarch. */ struct loongarch_gdbarch_tdep : gdbarch_tdep_base diff --git a/gdbserver/linux-loongarch-low.cc b/gdbserver/linux-loongarch-low.cc index c7328b2121e..f33c5a67882 100644 --- a/gdbserver/linux-loongarch-low.cc +++ b/gdbserver/linux-loongarch-low.cc @@ -177,12 +177,64 @@ loongarch_store_fpregset (struct regcache *regcache, const void *buf) supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf); } +/* Collect lsx regs from REGCACHE into BUF. */ + +static void +loongarch_fill_lsxregset (struct regcache *regcache, void *buf) +{ + elf_lsxregset_t *regset = (elf_lsxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + collect_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i); +} + +/* Supply lsx regs from BUF into REGCACHE. */ + +static void +loongarch_store_lsxregset (struct regcache *regcache, const void *buf) +{ + const elf_lsxregset_t *regset = (const elf_lsxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LSXREGSET; i++) + supply_register (regcache, LOONGARCH_FIRST_LSX_REGNUM + i, *regset + i); +} + +/* Collect lasx regs from REGCACHE into BUF. */ + +static void +loongarch_fill_lasxregset (struct regcache *regcache, void *buf) +{ + elf_lasxregset_t *regset = (elf_lasxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + collect_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i); +} + +/* Supply lasx regs from BUF into REGCACHE. */ + +static void +loongarch_store_lasxregset (struct regcache *regcache, const void *buf) +{ + const elf_lasxregset_t *regset = (const elf_lasxregset_t *) buf; + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_LASXREGSET; i++) + supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i); +} + /* LoongArch/Linux regsets. */ static struct regset_info loongarch_regsets[] = { { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t), GENERAL_REGS, loongarch_fill_gregset, loongarch_store_gregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET, sizeof (elf_fpregset_t), FP_REGS, loongarch_fill_fpregset, loongarch_store_fpregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LSX, sizeof (elf_lsxregset_t), + OPTIONAL_REGS, loongarch_fill_lsxregset, loongarch_store_lsxregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LASX, sizeof (elf_lasxregset_t), + OPTIONAL_REGS, loongarch_fill_lasxregset, loongarch_store_lasxregset }, NULL_REGSET }; From patchwork Thu Jan 25 08:32:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hui Li X-Patchwork-Id: 84716 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 356DA38582BF for ; Thu, 25 Jan 2024 08:33:25 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id 3930E3858C62 for ; Thu, 25 Jan 2024 08:32:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 3930E3858C62 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 3930E3858C62 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706171568; cv=none; b=k+rLseFQk72A0oVGfZKR5B6zCJZsCnEH+CMrLrihyNrZecEMDV4BPoNsxUmaKpJYT5lLrNXEqrdMc/Dex2wCqbSAax/yN4wnWePeJoEB2S9hwFIKC4NNPMg+rAPsMyVDSIwARPOEl9Eg4wZuHj2yR/t1C0yBv3LGviQEhf+sX6s= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1706171568; c=relaxed/simple; bh=Vf8OLj3MVDQMy6CIoQS4JgaoZVEWC9kACkB6uz2o3pU=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=XcVFhJOyVf/0Hd5FS5oOr0QKMDcjBXuial0t/DMcABlZKT62ZbyCiR/pnI1YRUOgj8iMnOLaKtEYn9t6RX6QGxAk6qxRM58gAqD1Dw3BQ6KpDR1n42jvDt59MC3c5ZwF9ecwmYqZuidjBw4YAibcPvCoW1q+Z1QxPK/e3BLbJho= ARC-Authentication-Results: i=1; server2.sourceware.org Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8AxOOioHLJlAHcFAA--.1001S3; Thu, 25 Jan 2024 16:32:40 +0800 (CST) Received: from localhost.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8BxXs2kHLJllgwZAA--.40368S4; Thu, 25 Jan 2024 16:32:40 +0800 (CST) From: Hui Li To: gdb-patches@sourceware.org, Tiezhu Yang Subject: [PATCH 2/2] gdb: LoongArch: Add LBT extension support Date: Thu, 25 Jan 2024 16:32:36 +0800 Message-Id: <20240125083236.28557-3-lihui@loongson.cn> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20240125083236.28557-1-lihui@loongson.cn> References: <20240125083236.28557-1-lihui@loongson.cn> MIME-Version: 1.0 X-CM-TRANSID: AQAAf8BxXs2kHLJllgwZAA--.40368S4 X-CM-SenderInfo: 5olk3xo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfJFWxJw18Cw1fur1fAF48KrX_yoW8AryrAo WfuF4Ygr4xGrWUAFy0yrnxJas0vFsxuw4fAa43Zwnxua1rtFs5GFyDKw1YvFy2yr1DGry8 AFWxt3Z7tayxWr1xl-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYT7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r1I6r4UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r1j6r4UM28EF7xvwVC2z280aVAFwI0_Gr1j6F4UJwA2z4x0Y4vEx4A2jsIEc7CjxVAF wI0_Gr1j6F4UJwAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI 0UMc02F40EFcxC0VAKzVAqx4xG6I80ewAv7VACjcxG62k0Y48FwI0_Jr0_Gr1lYx0E2Ix0 cI8IcVAFwI0_Jrv_JF1lYx0Ex4A2jsIE14v26r4UJVWxJr1lOx8S6xCaFVCjc4AY6r1j6r 4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4U MI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67 AKxVWUXVWUAwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0 cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z2 80aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVWUJVW8JbIYCTnIWIevJa73UjIF yTuYvjxU7s2-UUUUU X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org From: Feiyang Chen Loongson Binary Translation (LBT) is used to accelerate binary translation, which contains 4 scratch registers (scr0 to scr3), x86/ARM eflags (eflags) and x87 fpu stack pointer (ftop). This patch support gdb to fetch/store these registers. Signed-off-by: Feiyang Chen # Framework Signed-off-by: Binbin Zhou # Detail Optimizes Signed-off-by: Hui Li # Error Fixes --- gdb/arch/loongarch.c | 4 ++ gdb/arch/loongarch.h | 8 +++ gdb/features/Makefile | 1 + gdb/features/loongarch/lbt.c | 19 ++++++ gdb/features/loongarch/lbt.xml | 16 +++++ gdb/loongarch-linux-nat.c | 66 +++++++++++++++++++ gdb/loongarch-linux-tdep.c | 107 +++++++++++++++++++++++++++++++ gdb/loongarch-tdep.c | 18 ++++++ gdb/loongarch-tdep.h | 1 + gdbserver/linux-loongarch-low.cc | 43 +++++++++++++ 10 files changed, 283 insertions(+) create mode 100644 gdb/features/loongarch/lbt.c create mode 100644 gdb/features/loongarch/lbt.xml diff --git a/gdb/arch/loongarch.c b/gdb/arch/loongarch.c index e9995c9fe0f..22f2d3936ca 100644 --- a/gdb/arch/loongarch.c +++ b/gdb/arch/loongarch.c @@ -27,6 +27,7 @@ #include "../features/loongarch/fpu.c" #include "../features/loongarch/lsx.c" #include "../features/loongarch/lasx.c" +#include "../features/loongarch/lbt.c" #ifndef GDBSERVER #define STATIC_IN_GDB static @@ -69,6 +70,9 @@ loongarch_create_target_description (const struct loongarch_gdbarch_features fea regnum = create_feature_loongarch_lsx (tdesc.get (), regnum); regnum = create_feature_loongarch_lasx (tdesc.get (), regnum); + /* For now we only support creating scr registers, eflags and ftop. */ + regnum = create_feature_loongarch_lbt (tdesc.get (), regnum); + return tdesc; } diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h index d166f9d5eb9..4b7ab054ea0 100644 --- a/gdb/arch/loongarch.h +++ b/gdb/arch/loongarch.h @@ -45,6 +45,12 @@ enum loongarch_regnum LOONGARCH_LINUX_NUM_LSXREGSET = 32, LOONGARCH_FIRST_LASX_REGNUM = LOONGARCH_FIRST_LSX_REGNUM + LOONGARCH_LINUX_NUM_LSXREGSET, LOONGARCH_LINUX_NUM_LASXREGSET = 32, + + LOONGARCH_FIRST_SCR_REGNUM = LOONGARCH_FIRST_LASX_REGNUM + LOONGARCH_LINUX_NUM_LASXREGSET, + LOONGARCH_LINUX_NUM_SCR = 4, + LOONGARCH_LAST_SCR_REGNUM = LOONGARCH_FIRST_SCR_REGNUM + LOONGARCH_LINUX_NUM_SCR - 1, + LOONGARCH_EFLAGS_REGNUM = LOONGARCH_LAST_SCR_REGNUM + 1, + LOONGARCH_FTOP_REGNUM = LOONGARCH_EFLAGS_REGNUM + 1, }; enum loongarch_fputype @@ -53,6 +59,8 @@ enum loongarch_fputype DOUBLE_FLOAT = 2, }; + #define LOONGARCH_LBT_REGS_SIZE (8 * LOONGARCH_LINUX_NUM_SCR + 4 + 4) + /* The set of LoongArch architectural features that we track that impact how we configure the actual gdbarch instance. We hold one of these in the gdbarch_tdep structure, and use it to distinguish between different diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 7c33c093375..ddf4ec295a9 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -239,6 +239,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ loongarch/fpu.xml \ loongarch/lsx.xml \ loongarch/lasx.xml \ + loongarch/lbt.xml \ riscv/rv32e-xregs.xml \ riscv/32bit-cpu.xml \ riscv/32bit-fpu.xml \ diff --git a/gdb/features/loongarch/lbt.c b/gdb/features/loongarch/lbt.c new file mode 100644 index 00000000000..869c86248c4 --- /dev/null +++ b/gdb/features/loongarch/lbt.c @@ -0,0 +1,19 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: lbt.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_loongarch_lbt (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.loongarch.lbt"); + tdesc_create_reg (feature, "scr0", regnum++, 1, "lbt", 64, "uint64"); + tdesc_create_reg (feature, "scr1", regnum++, 1, "lbt", 64, "uint64"); + tdesc_create_reg (feature, "scr2", regnum++, 1, "lbt", 64, "uint64"); + tdesc_create_reg (feature, "scr3", regnum++, 1, "lbt", 64, "uint64"); + tdesc_create_reg (feature, "eflags", regnum++, 1, "lbt", 32, "uint32"); + tdesc_create_reg (feature, "ftop", regnum++, 1, "lbt", 32, "uint32"); + return regnum; +} diff --git a/gdb/features/loongarch/lbt.xml b/gdb/features/loongarch/lbt.xml new file mode 100644 index 00000000000..6526ee6068f --- /dev/null +++ b/gdb/features/loongarch/lbt.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c index 85d0a9619c0..9bceb8a5953 100644 --- a/gdb/loongarch-linux-nat.c +++ b/gdb/loongarch-linux-nat.c @@ -265,6 +265,70 @@ store_lasxregs_to_thread (struct regcache *regcache, int regnum, pid_t tid) } +/* Fill GDB's register array with the lbt register values + from the current thread. */ + +static void +fetch_lbt_from_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + gdb_byte regset[LOONGARCH_LBT_REGS_SIZE]; + + if (regnum == -1 + || (regnum >= LOONGARCH_FIRST_SCR_REGNUM + && regnum <= LOONGARCH_FTOP_REGNUM)) + { + struct iovec iov; + + iov.iov_base = regset; + iov.iov_len = LOONGARCH_LBT_REGS_SIZE; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0) + { + /* If kernel dose not support lbt, just return. */ + if (errno == EINVAL) + return; + perror_with_name (_("Couldn't get NT_LARCH_LBT registers")); + } + else + loongarch_lbtregset.supply_regset (nullptr, regcache, -1, + regset, LOONGARCH_LBT_REGS_SIZE); + } +} + +/* Store to the current thread the valid lbt register values + in the GDB's register array. */ + +static void +store_lbt_to_thread (struct regcache *regcache, int regnum, pid_t tid) +{ + gdb_byte regset[LOONGARCH_LBT_REGS_SIZE]; + + if (regnum == -1 + || (regnum >= LOONGARCH_FIRST_SCR_REGNUM + && regnum <= LOONGARCH_FTOP_REGNUM)) + { + struct iovec iov; + + iov.iov_base = regset; + iov.iov_len = LOONGARCH_LBT_REGS_SIZE; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0) + { + /* If kernel dose not support lbt, just return. */ + if (errno == EINVAL) + return; + perror_with_name (_("Couldn't get NT_LARCH_LBT registers")); + } + else + { + loongarch_lbtregset.collect_regset (nullptr, regcache, regnum, + regset, LOONGARCH_LBT_REGS_SIZE); + if (ptrace (PTRACE_SETREGSET, tid, NT_LARCH_LBT, (long) &iov) < 0) + perror_with_name (_("Couldn't set NT_LARCH_LBT registers")); + } + } +} + /* Implement the "fetch_registers" target_ops method. */ void @@ -277,6 +341,7 @@ loongarch_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_fpregs_from_thread(regcache, regnum, tid); fetch_lsxregs_from_thread(regcache, regnum, tid); fetch_lasxregs_from_thread(regcache, regnum, tid); + fetch_lbt_from_thread (regcache, regnum, tid); } /* Implement the "store_registers" target_ops method. */ @@ -291,6 +356,7 @@ loongarch_linux_nat_target::store_registers (struct regcache *regcache, store_fpregs_to_thread(regcache, regnum, tid); store_lsxregs_to_thread(regcache, regnum, tid); store_lasxregs_to_thread(regcache, regnum, tid); + store_lbt_to_thread (regcache, regnum, tid); } /* Return the address in the core dump or inferior of register REGNO. */ diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c index 726b6716270..0e82c09b4ff 100644 --- a/gdb/loongarch-linux-tdep.c +++ b/gdb/loongarch-linux-tdep.c @@ -338,6 +338,107 @@ const struct regset loongarch_lasxregset = loongarch_fill_lasxregset, }; +/* Unpack an lbt regset into GDB's register cache. */ + +static void +loongarch_supply_lbtregset (const struct regset *regset, + struct regcache *regcache, int regnum, + const void *regs, size_t len) +{ + int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM); + int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM); + const gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) + { + buf = (const gdb_byte *) regs + scrsize * i; + regcache->raw_supply (LOONGARCH_FIRST_SCR_REGNUM + i, + (const void *) buf); + } + + buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; + regcache->raw_supply (LOONGARCH_EFLAGS_REGNUM, (const void *) buf); + + buf = (const gdb_byte*) regs + + scrsize * LOONGARCH_LINUX_NUM_SCR + + eflagssize; + regcache->raw_supply (LOONGARCH_FTOP_REGNUM, (const void *) buf); + } + else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM + && regnum <= LOONGARCH_LAST_SCR_REGNUM) + { + buf = (const gdb_byte*) regs + + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM); + regcache->raw_supply (regnum, (const void *) buf); + } + else if (regnum == LOONGARCH_EFLAGS_REGNUM) + { + buf = (const gdb_byte*) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; + regcache->raw_supply (regnum, (const void *) buf); + } + else if (regnum == LOONGARCH_FTOP_REGNUM) + { + buf = (const gdb_byte*) regs + + scrsize * LOONGARCH_LINUX_NUM_SCR + + eflagssize; + regcache->raw_supply (regnum, (const void *) buf); + } +} + +/* Pack the GDB's register cache value into an lbt regset. */ + +static void +loongarch_fill_lbtregset (const struct regset *regset, + const struct regcache *regcache, int regnum, + void *regs, size_t len) +{ + int scrsize = register_size (regcache->arch (), LOONGARCH_FIRST_SCR_REGNUM); + int eflagssize = register_size (regcache->arch (), LOONGARCH_EFLAGS_REGNUM); + gdb_byte *buf = nullptr; + + if (regnum == -1) + { + for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) + { + buf = (gdb_byte *) regs + scrsize * i; + regcache->raw_collect (LOONGARCH_FIRST_SCR_REGNUM + i, (void *) buf); + } + + buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; + regcache->raw_collect (LOONGARCH_EFLAGS_REGNUM, (void *) buf); + + buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize; + regcache->raw_collect (LOONGARCH_FTOP_REGNUM, (void *) buf); + } + else if (regnum >= LOONGARCH_FIRST_SCR_REGNUM + && regnum <= LOONGARCH_LAST_SCR_REGNUM) + { + buf = (gdb_byte *) regs + scrsize * (regnum - LOONGARCH_FIRST_SCR_REGNUM); + regcache->raw_collect (regnum, (void *) buf); + } + else if (regnum == LOONGARCH_EFLAGS_REGNUM) + { + buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR; + regcache->raw_collect (regnum, (void *) buf); + } + else if (regnum == LOONGARCH_FTOP_REGNUM) + { + buf = (gdb_byte *) regs + scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize; + regcache->raw_collect (regnum, (void *) buf); + } +} + +/* Define the lbt register regset. */ + +const struct regset loongarch_lbtregset = +{ + nullptr, + loongarch_supply_lbtregset, + loongarch_fill_lbtregset, +}; + /* Implement the "init" method of struct tramp_frame. */ #define LOONGARCH_RT_SIGFRAME_UCONTEXT_OFFSET 128 @@ -394,6 +495,10 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch, fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize; int lsxrsize = register_size (gdbarch, LOONGARCH_FIRST_LSX_REGNUM); int lasxrsize = register_size (gdbarch, LOONGARCH_FIRST_LASX_REGNUM); + int scrsize = register_size (gdbarch, LOONGARCH_FIRST_SCR_REGNUM); + int eflagssize = register_size (gdbarch, LOONGARCH_EFLAGS_REGNUM); + int ftopsize = register_size (gdbarch, LOONGARCH_FTOP_REGNUM); + int lbtsize = scrsize * LOONGARCH_LINUX_NUM_SCR + eflagssize + ftopsize; cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize, LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data); @@ -402,6 +507,8 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch, &loongarch_lsxregset, nullptr, cb_data); cb (".reg-loongarch-lasx", lasxrsize, lasxrsize, &loongarch_lasxregset, nullptr, cb_data); + cb (".reg-loongarch-lbt", lbtsize, lbtsize, + &loongarch_lbtregset, nullptr, cb_data); } diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index f56e80f15b8..0f4622a55be 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -1743,6 +1743,24 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (!valid_p) return nullptr; + const struct tdesc_feature *feature_lbt + = tdesc_find_feature (tdesc, "org.gnu.gdb.loongarch.lbt"); + if (feature_lbt == nullptr) + return nullptr; + + /* Validate the description provides the lbt registers and + allocate their numbers. */ + regnum = LOONGARCH_FIRST_SCR_REGNUM; + for (int i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) + valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++, + loongarch_cr_normal_name[i] + 1); + valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++, + "eflags"); + valid_p &= tdesc_numbered_register (feature_lbt, tdesc_data.get (), regnum++, + "ftop"); + if (!valid_p) + return nullptr; + /* LoongArch code is always little-endian. */ info.byte_order_for_code = BFD_ENDIAN_LITTLE; diff --git a/gdb/loongarch-tdep.h b/gdb/loongarch-tdep.h index 6e0e798e6c8..bfe398898c0 100644 --- a/gdb/loongarch-tdep.h +++ b/gdb/loongarch-tdep.h @@ -32,6 +32,7 @@ extern const struct regset loongarch_gregset; extern const struct regset loongarch_fpregset; extern const struct regset loongarch_lsxregset; extern const struct regset loongarch_lasxregset; +extern const struct regset loongarch_lbtregset; /* Target-dependent structure in gdbarch. */ struct loongarch_gdbarch_tdep : gdbarch_tdep_base diff --git a/gdbserver/linux-loongarch-low.cc b/gdbserver/linux-loongarch-low.cc index f33c5a67882..f1e1deb878b 100644 --- a/gdbserver/linux-loongarch-low.cc +++ b/gdbserver/linux-loongarch-low.cc @@ -225,6 +225,47 @@ loongarch_store_lasxregset (struct regcache *regcache, const void *buf) supply_register (regcache, LOONGARCH_FIRST_LASX_REGNUM + i, *regset + i); } +/* Collect lbt regs from REGCACHE into BUF. */ + +static void +loongarch_fill_lbtregset (struct regcache *regcache, void *buf) +{ + gdb_byte *regbuf = (gdb_byte*)buf; + int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM); + int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM); + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) + collect_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i); + + collect_register (regcache, LOONGARCH_EFLAGS_REGNUM, + regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize); + collect_register (regcache, LOONGARCH_FTOP_REGNUM, + regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize); + +} + +/* Supply lbt regs from BUF into REGCACHE. */ + +static void +loongarch_store_lbtregset (struct regcache *regcache, const void *buf) +{ + + gdb_byte *regbuf = (gdb_byte*)buf; + int scrsize = register_size (regcache->tdesc, LOONGARCH_FIRST_SCR_REGNUM); + int eflagssize = register_size (regcache->tdesc, LOONGARCH_EFLAGS_REGNUM); + int i; + + for (i = 0; i < LOONGARCH_LINUX_NUM_SCR; i++) + supply_register (regcache, LOONGARCH_FIRST_SCR_REGNUM + i, regbuf + scrsize * i); + + supply_register (regcache, LOONGARCH_EFLAGS_REGNUM, + regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize); + supply_register (regcache, LOONGARCH_FTOP_REGNUM, + regbuf + LOONGARCH_LINUX_NUM_SCR * scrsize + eflagssize); + +} + /* LoongArch/Linux regsets. */ static struct regset_info loongarch_regsets[] = { { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS, sizeof (elf_gregset_t), @@ -235,6 +276,8 @@ static struct regset_info loongarch_regsets[] = { OPTIONAL_REGS, loongarch_fill_lsxregset, loongarch_store_lsxregset }, { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LASX, sizeof (elf_lasxregset_t), OPTIONAL_REGS, loongarch_fill_lasxregset, loongarch_store_lasxregset }, + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_LARCH_LBT, LOONGARCH_LBT_REGS_SIZE, + OPTIONAL_REGS, loongarch_fill_lbtregset, loongarch_store_lbtregset }, NULL_REGSET };