From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by sourceware.org (Postfix) with ESMTP id CF8EC3858D20 for ; Tue, 29 Aug 2023 12:10:52 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CF8EC3858D20 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [113.200.148.30]) by gateway (Coremail) with SMTP id _____8DxPOtH4O1kb8EcAA--.53409S3; Tue, 29 Aug 2023 20:10:48 +0800 (CST) Received: from localhost.localdomain (unknown [113.200.148.30]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Bx3yNH4O1kZ3NmAA--.10988S2; Tue, 29 Aug 2023 20:10:47 +0800 (CST) From: Hui Li To: gdb-patches@sourceware.org Cc: Tiezhu Yang Subject: [PATCH] gdb: LoongArch: Add vector extensions support Date: Tue, 29 Aug 2023 20:10:41 +0800 Message-Id: <20230829121041.13650-1-lihui@loongson.cn> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID:AQAAf8Bx3yNH4O1kZ3NmAA--.10988S2 X-CM-SenderInfo: 5olk3xo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfur17Xw13Zw47Xw1UKr4fCrX_yoW5ZryrZo ZY9F4Yq3W8GFWxAF1Iqwn8Ja4vqr45Crs3ZayUWasIka1fCFW5G3Wqqw13XFySqw4kG34U XrWxJ3srXFZrZr4fl-sFpf9Il3svdjkaLaAFLSUrUUUUUb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUUYU7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26ryj6F1UM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_Cr1j6rxdM28EF7xvwVC2z280aVCY1x0267AK xVW0oVCq3wAS0I0E0xvYzxvE52x082IY62kv0487Mc804VCY07AIYIkI8VC2zVCFFI0UMc 02F40EFcxC0VAKzVAqx4xG6I80ewAv7VC0I7IYx2IY67AKxVWUJVWUGwAv7VC2z280aVAF wI0_Jr0_Gr1lOx8S6xCaFVCjc4AY6r1j6r4UM4x0Y48IcxkI7VAKI48JMxAIw28IcxkI7V AKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I8CrVAFwI0_Jr0_Jr4lx2IqxVCj r7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUXVWUAwCIc40Y0x0EwIxGrwCI42IY6x IIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x0267AKxVWUJVW8JwCI42IY6xAI w20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x 0267AKxVWUJVW8JbIYCTnIWIevJa73UjIFyTuYvjxUzsqWUUUUU X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_STATUS,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Add LoongArch's vector extensions support, which including 128bit LSX (i.e., Loongson SIMD eXtension) and 256bit LASX (i.e., Loongson Advanced SIMD eXtension). Signed-off-by: Hui Li Change-Id: I04e92203a86547654d9f6c8cd1a9c3a789cb73db --- gdb/arch/loongarch.c | 7 ++ gdb/arch/loongarch.h | 4 + gdb/features/Makefile | 2 + gdb/features/loongarch/lasx.c | 85 +++++++++++++++++++++ gdb/features/loongarch/lasx.xml | 61 ++++++++++++++++ gdb/features/loongarch/lsx.c | 82 +++++++++++++++++++++ gdb/features/loongarch/lsx.xml | 60 +++++++++++++++ gdb/loongarch-linux-nat.c | 123 +++++++++++++++++++++++++++++++ gdb/loongarch-linux-tdep.c | 126 ++++++++++++++++++++++++++++++++ gdb/loongarch-tdep.c | 32 ++++++++ gdb/loongarch-tdep.h | 2 + 11 files changed, 584 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 168fcbc15df..1fb3c24149e 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,11 @@ 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 d0a63dc2ac5..48662af8c11 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 32341f71815..965e32d3f04 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..c6ce56660f2 --- /dev/null +++ b/gdb/features/loongarch/lasx.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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..7813f62052c --- /dev/null +++ b/gdb/features/loongarch/lsx.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/loongarch-linux-nat.c b/gdb/loongarch-linux-nat.c index 5eb32b0a52a..af571059a47 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) + { + /* The kernel may not support lsx, so here 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) + { + /* The kernel may not support lsx, so here 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) + { + /* The kernel may not support lasx, so here 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) + { + /* The kernel may not support lasx, so here 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 ebd26d5e90e..93ebf814189 100644 --- a/gdb/loongarch-linux-tdep.c +++ b/gdb/loongarch-linux-tdep.c @@ -215,6 +215,127 @@ 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_FIRST_LASX_REGNUM) + { + 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) + { + 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 +390,15 @@ 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, "LoongArch SIMD Extension", cb_data); //FIXME + cb (".reg-loongarch-lasx", lasxrsize, lasxrsize, &loongarch_lasxregset, "LoongArch Advanced SIMD Extension", 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 74f14c40d51..05fe7a95101 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -1476,6 +1476,10 @@ 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; + int ret = tdesc_register_in_reggroup_p (gdbarch, regnum, group); if (ret != -1) return ret; @@ -1533,6 +1537,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 dc80cef468b..b4d7499d4d0 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 -- 2.20.1