Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH v2] gdb/gdbserver: LoongArch: Improve implementation of fcc registers
@ 2022-08-02  9:16 Feiyang Chen via Gdb-patches
  2022-08-09 14:27 ` Tiezhu Yang
  0 siblings, 1 reply; 2+ messages in thread
From: Feiyang Chen via Gdb-patches @ 2022-08-02  9:16 UTC (permalink / raw)
  To: yangtiezhu; +Cc: chris.chenfeiyang, Feiyang Chen, gdb-patches

The current implementation of the fcc register is referenced to the
user_fp_state structure of the kernel uapi [1]. But it is mistakenly
defined as a 64-bit fputype register, resulting in in a confusing
output of "info register".

(gdb) info register
...
fcc            {f = 0x0, d = 0x0}  {f = 0, d = 0}
...

According to "Condition Flag Register" in "LoongArch Reference Manual"
[2], there are 8 condition flag registers of size 1. Use 8 registers of
uint8 to make it easier for users to view the fcc register groups.

(gdb) info register
...
fcc0           0x1                 1
fcc1           0x0                 0
fcc2           0x0                 0
fcc3           0x0                 0
fcc4           0x0                 0
fcc5           0x0                 0
fcc6           0x0                 0
fcc7           0x0                 0
...

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/uapi/asm/ptrace.h
[2] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_condition_flag_register

Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
---
 gdb/arch/loongarch.h             |  7 ++--
 gdb/features/loongarch/fpu.c     |  9 +++++-
 gdb/features/loongarch/fpu.xml   |  9 +++++-
 gdb/loongarch-linux-tdep.c       | 55 +++++++++++++++++++++++++++++---
 gdb/loongarch-tdep.c             |  6 ++--
 gdbserver/linux-loongarch-low.cc | 24 ++++++++++++++
 6 files changed, 99 insertions(+), 11 deletions(-)

diff --git a/gdb/arch/loongarch.h b/gdb/arch/loongarch.h
index 799595b3e60..eae061f7f47 100644
--- a/gdb/arch/loongarch.h
+++ b/gdb/arch/loongarch.h
@@ -37,9 +37,10 @@ enum loongarch_regnum
   LOONGARCH_ARG_REGNUM = 8,            /* r4-r11: general-purpose argument registers.
 					  f0-f7: floating-point argument registers.  */
   LOONGARCH_FIRST_FP_REGNUM = LOONGARCH_LINUX_NUM_GREGSET,
-  LOONGARCH_FCC_REGNUM = LOONGARCH_FIRST_FP_REGNUM + 32,
-  LOONGARCH_FCSR_REGNUM = LOONGARCH_FCC_REGNUM + 1,
-  LOONGARCH_LINUX_NUM_FPREGSET = 34,
+  LOONGARCH_LINUX_NUM_FPREGSET = 32,
+  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,
 };
 
 enum loongarch_fputype
diff --git a/gdb/features/loongarch/fpu.c b/gdb/features/loongarch/fpu.c
index ea3e1dd9980..183ed54989f 100644
--- a/gdb/features/loongarch/fpu.c
+++ b/gdb/features/loongarch/fpu.c
@@ -49,7 +49,14 @@ create_feature_loongarch_fpu (struct target_desc *result, long regnum)
   tdesc_create_reg (feature, "f29", regnum++, 1, "float", 64, "fputype");
   tdesc_create_reg (feature, "f30", regnum++, 1, "float", 64, "fputype");
   tdesc_create_reg (feature, "f31", regnum++, 1, "float", 64, "fputype");
-  tdesc_create_reg (feature, "fcc", regnum++, 1, "float", 64, "fputype");
+  tdesc_create_reg (feature, "fcc0", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc1", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc2", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc3", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc4", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc5", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc6", regnum++, 1, "float", 8, "uint8");
+  tdesc_create_reg (feature, "fcc7", regnum++, 1, "float", 8, "uint8");
   tdesc_create_reg (feature, "fcsr", regnum++, 1, "float", 32, "uint32");
   return regnum;
 }
diff --git a/gdb/features/loongarch/fpu.xml b/gdb/features/loongarch/fpu.xml
index a61057ec442..e81e3382e7d 100644
--- a/gdb/features/loongarch/fpu.xml
+++ b/gdb/features/loongarch/fpu.xml
@@ -45,6 +45,13 @@
   <reg name="f29" bitsize="64" type="fputype" group="float"/>
   <reg name="f30" bitsize="64" type="fputype" group="float"/>
   <reg name="f31" bitsize="64" type="fputype" group="float"/>
-  <reg name="fcc" bitsize="64" type="fputype" group="float"/>
+  <reg name="fcc0" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc1" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc2" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc3" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc4" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc5" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc6" bitsize="8" type="uint8" group="float"/>
+  <reg name="fcc7" bitsize="8" type="uint8" group="float"/>
   <reg name="fcsr" bitsize="32" type="uint32" group="float"/>
 </feature>
diff --git a/gdb/loongarch-linux-tdep.c b/gdb/loongarch-linux-tdep.c
index 3a81ff31972..883245bec7e 100644
--- a/gdb/loongarch-linux-tdep.c
+++ b/gdb/loongarch-linux-tdep.c
@@ -123,6 +123,7 @@ loongarch_supply_fpregset (const struct regset *r,
 {
   const gdb_byte *buf = nullptr;
   int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM);
+  int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM);
 
   if (regnum == -1)
     {
@@ -131,12 +132,33 @@ loongarch_supply_fpregset (const struct regset *r,
 	  buf = (const gdb_byte *)fprs + fprsize * i;
 	  regcache->raw_supply (LOONGARCH_FIRST_FP_REGNUM + i, (const void *)buf);
 	}
+      for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
+	{
+	  buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	    fccsize * i;
+	  regcache->raw_supply (LOONGARCH_FIRST_FCC_REGNUM + i, (const void *)buf);
+	}
+      buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * LOONGARCH_LINUX_NUM_FCC;
+      regcache->raw_supply (LOONGARCH_FCSR_REGNUM, (const void *)buf);
     }
-  else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum <= LOONGARCH_FCSR_REGNUM)
+  else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM)
     {
       buf = (const gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM);
       regcache->raw_supply (regnum, (const void *)buf);
     }
+  else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM)
+    {
+      buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM);
+      regcache->raw_supply (regnum, (const void *)buf);
+    }
+  else if (regnum == LOONGARCH_FCSR_REGNUM)
+    {
+      buf = (const gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * LOONGARCH_LINUX_NUM_FCC;
+      regcache->raw_supply (regnum, (const void *)buf);
+    }
 }
 
 /* Pack the GDB's register cache value into an elf_fpregset_t.  */
@@ -147,6 +169,7 @@ loongarch_fill_fpregset (const struct regset *r,
 {
   gdb_byte *buf = nullptr;
   int fprsize = register_size (regcache->arch (), LOONGARCH_FIRST_FP_REGNUM);
+  int fccsize = register_size (regcache->arch (), LOONGARCH_FIRST_FCC_REGNUM);
 
   if (regnum == -1)
     {
@@ -155,12 +178,33 @@ loongarch_fill_fpregset (const struct regset *r,
 	  buf = (gdb_byte *)fprs + fprsize * i;
 	  regcache->raw_collect (LOONGARCH_FIRST_FP_REGNUM + i, (void *)buf);
 	}
+      for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
+	{
+	  buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	    fccsize * i;
+	  regcache->raw_collect (LOONGARCH_FIRST_FCC_REGNUM + i, (void *)buf);
+	}
+      buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * LOONGARCH_LINUX_NUM_FCC;
+      regcache->raw_collect (LOONGARCH_FCSR_REGNUM, (void *)buf);
     }
-  else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum <= LOONGARCH_FCSR_REGNUM)
+  else if (regnum >= LOONGARCH_FIRST_FP_REGNUM && regnum < LOONGARCH_FIRST_FCC_REGNUM)
     {
       buf = (gdb_byte *)fprs + fprsize * (regnum - LOONGARCH_FIRST_FP_REGNUM);
       regcache->raw_collect (regnum, (void *)buf);
     }
+  else if (regnum >= LOONGARCH_FIRST_FCC_REGNUM && regnum < LOONGARCH_FCSR_REGNUM)
+    {
+      buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * (regnum - LOONGARCH_FIRST_FCC_REGNUM);
+      regcache->raw_collect (regnum, (void *)buf);
+    }
+  else if (regnum == LOONGARCH_FCSR_REGNUM)
+    {
+      buf = (gdb_byte *)fprs + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * LOONGARCH_LINUX_NUM_FCC;
+      regcache->raw_collect (regnum, (void *)buf);
+    }
 }
 
 /* Define the FP register regset.  */
@@ -221,11 +265,14 @@ loongarch_iterate_over_regset_sections (struct gdbarch *gdbarch,
 {
   int gprsize = register_size (gdbarch, 0);
   int fprsize = register_size (gdbarch, LOONGARCH_FIRST_FP_REGNUM);
+  int fccsize = register_size (gdbarch, LOONGARCH_FIRST_FCC_REGNUM);
+  int fcsrsize = register_size (gdbarch, LOONGARCH_FCSR_REGNUM);
+  int fpsize = fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+    fccsize * LOONGARCH_LINUX_NUM_FCC + fcsrsize;
 
   cb (".reg", LOONGARCH_LINUX_NUM_GREGSET * gprsize,
       LOONGARCH_LINUX_NUM_GREGSET * gprsize, &loongarch_gregset, nullptr, cb_data);
-  cb (".reg2", LOONGARCH_LINUX_NUM_FPREGSET * fprsize,
-      LOONGARCH_LINUX_NUM_FPREGSET * fprsize, &loongarch_fpregset, nullptr, cb_data);
+  cb (".reg2", fpsize, fpsize, &loongarch_fpregset, 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 85a1dd70ebd..e63ff01854d 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -1428,10 +1428,12 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   /* Validate the description provides the fpu registers and
      allocate their numbers.  */
   regnum = LOONGARCH_FIRST_FP_REGNUM;
-  for (int i = 0; i < 32; i++)
+  for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
     valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++,
 					loongarch_f_normal_name[i] + 1);
-  valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++, "fcc");
+  for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
+    valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++,
+					loongarch_c_normal_name[i] + 1);
   valid_p &= tdesc_numbered_register (feature_fpu, tdesc_data.get (), regnum++, "fcsr");
   if (!valid_p)
     return nullptr;
diff --git a/gdbserver/linux-loongarch-low.cc b/gdbserver/linux-loongarch-low.cc
index 7180f315b11..cccf1ba780b 100644
--- a/gdbserver/linux-loongarch-low.cc
+++ b/gdbserver/linux-loongarch-low.cc
@@ -127,12 +127,24 @@ loongarch_fill_fpregset (struct regcache *regcache, void *buf)
 {
   gdb_byte *regbuf = nullptr;
   int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
+  int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
 
   for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
     {
       regbuf = (gdb_byte *)buf + fprsize * i;
       collect_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
     }
+
+  for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
+    {
+      regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * i;
+      collect_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
+    }
+
+  regbuf = (gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+    fccsize * LOONGARCH_LINUX_NUM_FCC;
+  collect_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
 }
 
 /* Supply FPRs from BUF into REGCACHE.  */
@@ -142,12 +154,24 @@ loongarch_store_fpregset (struct regcache *regcache, const void *buf)
 {
   const gdb_byte *regbuf = nullptr;
   int fprsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FP_REGNUM);
+  int fccsize = register_size (regcache->tdesc, LOONGARCH_FIRST_FCC_REGNUM);
 
   for (int i = 0; i < LOONGARCH_LINUX_NUM_FPREGSET; i++)
     {
       regbuf = (const gdb_byte *)buf + fprsize * i;
       supply_register (regcache, LOONGARCH_FIRST_FP_REGNUM + i, regbuf);
     }
+
+  for (int i = 0; i < LOONGARCH_LINUX_NUM_FCC; i++)
+    {
+      regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+	fccsize * i;
+      supply_register (regcache, LOONGARCH_FIRST_FCC_REGNUM + i, regbuf);
+    }
+
+  regbuf = (const gdb_byte *)buf + fprsize * LOONGARCH_LINUX_NUM_FPREGSET +
+    fccsize * LOONGARCH_LINUX_NUM_FCC;
+  supply_register (regcache, LOONGARCH_FCSR_REGNUM, regbuf);
 }
 
 /* LoongArch/Linux regsets.  */
-- 
2.37.1


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH v2] gdb/gdbserver: LoongArch: Improve implementation of fcc registers
  2022-08-02  9:16 [PATCH v2] gdb/gdbserver: LoongArch: Improve implementation of fcc registers Feiyang Chen via Gdb-patches
@ 2022-08-09 14:27 ` Tiezhu Yang
  0 siblings, 0 replies; 2+ messages in thread
From: Tiezhu Yang @ 2022-08-09 14:27 UTC (permalink / raw)
  To: Feiyang Chen; +Cc: Feiyang Chen, gdb-patches



On 8/2/22 17:16, Feiyang Chen wrote:
> The current implementation of the fcc register is referenced to the
> user_fp_state structure of the kernel uapi [1]. But it is mistakenly
> defined as a 64-bit fputype register, resulting in in a confusing
> output of "info register".
> 
> (gdb) info register
> ...
> fcc            {f = 0x0, d = 0x0}  {f = 0, d = 0}
> ...
> 
> According to "Condition Flag Register" in "LoongArch Reference Manual"
> [2], there are 8 condition flag registers of size 1. Use 8 registers of
> uint8 to make it easier for users to view the fcc register groups.
> 
> (gdb) info register
> ...
> fcc0           0x1                 1
> fcc1           0x0                 0
> fcc2           0x0                 0
> fcc3           0x0                 0
> fcc4           0x0                 0
> fcc5           0x0                 0
> fcc6           0x0                 0
> fcc7           0x0                 0
> ...
> 
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/loongarch/include/uapi/asm/ptrace.h
> [2] https://loongson.github.io/LoongArch-Documentation/LoongArch-Vol1-EN.html#_condition_flag_register
> 
> Signed-off-by: Feiyang Chen <chenfeiyang@loongson.cn>
> ---
>   gdb/arch/loongarch.h             |  7 ++--
>   gdb/features/loongarch/fpu.c     |  9 +++++-
>   gdb/features/loongarch/fpu.xml   |  9 +++++-
>   gdb/loongarch-linux-tdep.c       | 55 +++++++++++++++++++++++++++++---
>   gdb/loongarch-tdep.c             |  6 ++--
>   gdbserver/linux-loongarch-low.cc | 24 ++++++++++++++
>   6 files changed, 99 insertions(+), 11 deletions(-)

Thanks for the detailed commit message in this version.
Looks good to me, tested on LoongArch, pushed.

Thanks,
Tiezhu


^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2022-08-09 14:27 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-02  9:16 [PATCH v2] gdb/gdbserver: LoongArch: Improve implementation of fcc registers Feiyang Chen via Gdb-patches
2022-08-09 14:27 ` Tiezhu Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox