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 58CAD3858C53 for ; Fri, 25 Aug 2023 10:11:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 58CAD3858C53 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 [112.20.109.102]) by gateway (Coremail) with SMTP id _____8BxY_BUfuhkEMwbAA--.56778S3; Fri, 25 Aug 2023 18:11:33 +0800 (CST) Received: from localhost.localdomain (unknown [112.20.109.102]) by localhost.localdomain (Coremail) with SMTP id AQAAf8CxriNTfuhkWlFjAA--.4342S2; Fri, 25 Aug 2023 18:11:31 +0800 (CST) From: Feiyang Chen To: yangtiezhu@loongson.cn Cc: Feiyang Chen , chris.chenfeiyang@gmail.com, gdb-patches@sourceware.org, zhoubinbin@loongson.cn, chenhuacai@loongson.cn Subject: [PATCH] gdb: LoongArch: Support LBT registers Date: Fri, 25 Aug 2023 18:11:13 +0800 Message-Id: <20230825101113.3527944-1-chenfeiyang@loongson.cn> X-Mailer: git-send-email 2.39.3 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-CM-TRANSID:AQAAf8CxriNTfuhkWlFjAA--.4342S2 X-CM-SenderInfo: hfkh0wphl1t03j6o00pqjv00gofq/ X-Coremail-Antispam: 1Uk129KBj9fXoWfJFW3JF47Cry3ZF1kJr47trc_yoW8Xw1Uto WfuF4jgr48GrW8AF1FyrnxJas0qr47uw4fAasxZwn7ua1rtFs8GFykKw1YvF17Zr1DGrW8 Ca97t3Z2yay7Wr1fl-sFpf9Il3svdjkaLaAFLSUrUUUUjb8apTn2vfkv8UJUUUU8wcxFpf 9Il3svdxBIdaVrn0xqx4xG64xvF2IEw4CE5I8CrVC2j2Jv73VFW2AGmfu7bjvjm3AaLaJ3 UjIYCTnIWjp_UUU5R7kC6x804xWl14x267AKxVWUJVW8JwAFc2x0x2IEx4CE42xK8VAvwI 8IcIk0rVWrJVCq3wAFIxvE14AKwVWUJVWUGwA2ocxC64kIII0Yj41l84x0c7CEw4AK67xG Y2AK021l84ACjcxK6xIIjxv20xvE14v26r4j6ryUM28EF7xvwVC0I7IYx2IY6xkF7I0E14 v26r4j6F4UM28EF7xvwVC2z280aVAFwI0_GcCE3s1l84ACjcxK6I8E87Iv6xkF7I0E14v2 6rxl6s0DM2AIxVAIcxkEcVAq07x20xvEncxIr21l57IF6xkI12xvs2x26I8E6xACxx1l5I 8CrVACY4xI64kE6c02F40Ex7xfMcIj6xIIjxv20xvE14v26r106r15McIj6I8E87Iv67AK xVWUJVW8JwAm72CE4IkC6x0Yz7v_Jr0_Gr1lF7xvr2IYc2Ij64vIr41l42xK82IYc2Ij64 vIr41l4I8I3I0E4IkC6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8G jcxK67AKxVWUGVWUWwC2zVAF1VAY17CE14v26r126r1DMIIYrxkI7VAKI48JMIIF0xvE2I x0cI8IcVAFwI0_Jr0_JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26r1j6r4UMIIF0xvE42xK 8VAvwI8IcIk0rVWUJVWUCwCI42IY6I8E87Iv67AKxVWUJVW8JwCI42IY6I8E87Iv6xkF7I 0E14v26r1j6r4UYxBIdaVFxhVjvjDU0xZFpf9x07UWHqcUUUUU= X-Spam-Status: No, score=-13.7 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 LBT registers ($scrx, $eflags, $ftop) support for LoongArch. Co-authored-by: Binbin Zhou --- gdb/arch/loongarch.c | 4 ++ gdb/arch/loongarch.h | 7 +++ gdb/features/Makefile | 1 + gdb/features/loongarch/lbt.c | 19 +++++++ gdb/features/loongarch/lbt.xml | 16 ++++++ gdb/loongarch-linux-nat.c | 54 ++++++++++++++++++ gdb/loongarch-linux-tdep.c | 98 ++++++++++++++++++++++++++++++++ gdb/loongarch-tdep.c | 15 +++++ gdb/loongarch-tdep.h | 1 + gdbserver/linux-loongarch-low.cc | 8 +++ 10 files changed, 223 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 168fcbc15df..255531a50f7 100644 --- a/gdb/arch/loongarch.c +++ b/gdb/arch/loongarch.c @@ -25,6 +25,7 @@ #include "../features/loongarch/base32.c" #include "../features/loongarch/base64.c" #include "../features/loongarch/fpu.c" +#include "../features/loongarch/lbt.c" #ifndef GDBSERVER #define STATIC_IN_GDB static @@ -63,6 +64,9 @@ 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 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 d0a63dc2ac5..73f3d64fb16 100644 --- a/gdb/arch/loongarch.h +++ b/gdb/arch/loongarch.h @@ -41,6 +41,11 @@ 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_SCR_REGNUM = LOONGARCH_FCSR_REGNUM + 1, + LOONGARCH_LINUX_NUM_SCR = 4, + LOONGARCH_SCR_REGNUM = LOONGARCH_FCSR_REGNUM + LOONGARCH_LINUX_NUM_SCR, + LOONGARCH_EFLAGS_REGNUM = LOONGARCH_SCR_REGNUM + 1, + LOONGARCH_FTOP_REGNUM = LOONGARCH_EFLAGS_REGNUM + 1, }; enum loongarch_fputype @@ -49,6 +54,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 32341f71815..1d8221166e8 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -237,6 +237,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ loongarch/base32.xml \ loongarch/base64.xml \ loongarch/fpu.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..02cf6ba9358 --- /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, "general", 64, "uint64"); + tdesc_create_reg (feature, "scr1", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "scr2", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "scr3", regnum++, 1, "general", 64, "uint64"); + tdesc_create_reg (feature, "eflags", regnum++, 1, "general", 32, "uint32"); + tdesc_create_reg (feature, "ftop", regnum++, 1, "general", 32, "uint32"); + return regnum; +} diff --git a/gdb/features/loongarch/lbt.xml b/gdb/features/loongarch/lbt.xml new file mode 100644 index 00000000000..d01311dfab6 --- /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 40231d5d753..184a6715103 100644 --- a/gdb/loongarch-linux-nat.c +++ b/gdb/loongarch-linux-nat.c @@ -146,6 +146,58 @@ store_fpregs_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_SCR_REGNUM)) + { + struct iovec iov; + + iov.iov_base = regset; + iov.iov_len = LOONGARCH_LBT_REGS_SIZE; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LOONGARCH_LBT, (long) &iov) < 0) + perror_with_name (_("Couldn't get NT_LOONGARCH_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_SCR_REGNUM)) + { + struct iovec iov; + + iov.iov_base = regset; + iov.iov_len = LOONGARCH_LBT_REGS_SIZE; + + if (ptrace (PTRACE_GETREGSET, tid, NT_LOONGARCH_LBT, (long) &iov) < 0) + perror_with_name (_("Couldn't get NT_LOONGARCH_LBT registers")); + else + { + loongarch_lbtregset.collect_regset (nullptr, regcache, regnum, + regset, LOONGARCH_LBT_REGS_SIZE); + if (ptrace (PTRACE_SETREGSET, tid, NT_LOONGARCH_LBT, (long) &iov) < 0) + perror_with_name (_("Couldn't set NT_LOONGARCH_LBT registers")); + } + } +} + /* Implement the "fetch_registers" target_ops method. */ void @@ -156,6 +208,7 @@ loongarch_linux_nat_target::fetch_registers (struct regcache *regcache, fetch_gregs_from_thread(regcache, regnum, tid); fetch_fpregs_from_thread(regcache, regnum, tid); + fetch_lbt_from_thread (regcache, regnum, tid); } /* Implement the "store_registers" target_ops method. */ @@ -168,6 +221,7 @@ loongarch_linux_nat_target::store_registers (struct regcache *regcache, store_gregs_to_thread (regcache, regnum, tid); store_fpregs_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 ebd26d5e90e..62fd0aba268 100644 --- a/gdb/loongarch-linux-tdep.c +++ b/gdb/loongarch-linux-tdep.c @@ -215,6 +215,99 @@ const struct regset loongarch_fpregset = loongarch_fill_fpregset, }; +/* Unpack an elf_gregset_t 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_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 elf_gregset_t. */ + +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_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 @@ -269,10 +362,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 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); cb (".reg2", fpsize, fpsize, &loongarch_fpregset, nullptr, cb_data); + cb (".reg-loongarch-lbt", lbtsize, lbtsize, &loongarch_lbtregset, 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 62c6f9b220e..c463115e95a 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -1533,6 +1533,21 @@ 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. */ + 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 dc80cef468b..14aa1fe7098 100644 --- a/gdb/loongarch-tdep.h +++ b/gdb/loongarch-tdep.h @@ -30,6 +30,7 @@ /* Register set definitions. */ extern const struct regset loongarch_gregset; extern const struct regset loongarch_fpregset; +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 ead2e76d25d..66957789844 100644 --- a/gdbserver/linux-loongarch-low.cc +++ b/gdbserver/linux-loongarch-low.cc @@ -102,6 +102,10 @@ loongarch_fill_gregset (struct regcache *regcache, void *buf) collect_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM); collect_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM); collect_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM); + for (i = LOONGARCH_FIRST_SCR_REGNUM; i < LOONGARCH_SCR_REGNUM; i++) + collect_register (regcache, i, *regset + i); + collect_register (regcache, LOONGARCH_EFLAGS_REGNUM, *regset + LOONGARCH_EFLAGS_REGNUM); + collect_register (regcache, LOONGARCH_FTOP_REGNUM, *regset + LOONGARCH_FTOP_REGNUM); } /* Supply GPRs from BUF into REGCACHE. */ @@ -118,6 +122,10 @@ loongarch_store_gregset (struct regcache *regcache, const void *buf) supply_register (regcache, LOONGARCH_ORIG_A0_REGNUM, *regset + LOONGARCH_ORIG_A0_REGNUM); supply_register (regcache, LOONGARCH_PC_REGNUM, *regset + LOONGARCH_PC_REGNUM); supply_register (regcache, LOONGARCH_BADV_REGNUM, *regset + LOONGARCH_BADV_REGNUM); + for (i = LOONGARCH_FIRST_SCR_REGNUM; i < LOONGARCH_SCR_REGNUM; i++) + supply_register (regcache, i, *regset + i); + supply_register (regcache, LOONGARCH_EFLAGS_REGNUM, *regset + LOONGARCH_EFLAGS_REGNUM); + supply_register (regcache, LOONGARCH_FTOP_REGNUM, *regset + LOONGARCH_FTOP_REGNUM); } /* Collect FPRs from REGCACHE into BUF. */ -- 2.39.3