public inbox for gdb-cvs@sourceware.org
help / color / mirror / Atom feed
* [binutils-gdb] gdb: LoongArch: Implement the software_single_step gdbarch method
@ 2022-06-02 14:46 Tiezhu Yang
  0 siblings, 0 replies; only message in thread
From: Tiezhu Yang @ 2022-06-02 14:46 UTC (permalink / raw)
  To: gdb-cvs

https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=2e90d0257855fa4661f2da67033286958632ed55

commit 2e90d0257855fa4661f2da67033286958632ed55
Author: Tiezhu Yang <yangtiezhu@loongson.cn>
Date:   Thu Jun 2 14:51:17 2022 +0800

    gdb: LoongArch: Implement the software_single_step gdbarch method
    
    When execute the following command on LoongArch:
    
      make check-gdb TESTS="gdb.base/branch-to-self.exp"
    
    there exist the following failed testcases:
    
      FAIL: gdb.base/branch-to-self.exp: single-step: si (timeout)
      FAIL: gdb.base/branch-to-self.exp: break-cond: side=host: continue to breakpoint: continue to break (timeout)
      FAIL: gdb.base/branch-to-self.exp: break-cond: side=host: p counter (timeout)
    
    Implement the software_single_step gdbarch method to decode the current
    branch instruction and determine the address of the next instruction on
    LoongArch to fix the above failed testcases.
    
    Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>

Diff:
---
 gdb/loongarch-tdep.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 105 insertions(+)

diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c
index 8e74c9b779d..963e832454a 100644
--- a/gdb/loongarch-tdep.c
+++ b/gdb/loongarch-tdep.c
@@ -178,6 +178,110 @@ loongarch_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR pc)
   return loongarch_scan_prologue (gdbarch, pc, limit_pc, nullptr, nullptr);
 }
 
+/* Decode the current instruction and determine the address of the
+   next instruction.  */
+
+static CORE_ADDR
+loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc, insn_t insn)
+{
+  size_t insn_len = loongarch_insn_length (insn);
+  CORE_ADDR next_pc = cur_pc + insn_len;
+
+  if ((insn & 0xfc000000) == 0x4c000000)		/* jirl rd, rj, offs16  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      next_pc = rj + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x50000000		/* b    offs26  */
+	   || (insn & 0xfc000000) == 0x54000000)	/* bl	offs26  */
+    {
+      next_pc = cur_pc + loongarch_decode_imm ("0:10|10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x58000000)		/* beq	rj, rd, offs16  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      LONGEST rd = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("0:5", insn, 0));
+      if (rj == rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x5c000000)		/* bne	rj, rd, offs16  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      LONGEST rd = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("0:5", insn, 0));
+      if (rj != rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x60000000)		/* blt	rj, rd, offs16  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      LONGEST rd = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("0:5", insn, 0));
+      if (rj < rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x64000000)		/* bge	rj, rd, offs16  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      LONGEST rd = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("0:5", insn, 0));
+      if (rj >= rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x68000000)		/* bltu	rj, rd, offs16  */
+    {
+      ULONGEST rj = regcache_raw_get_unsigned (regcache,
+		      loongarch_decode_imm ("5:5", insn, 0));
+      ULONGEST rd = regcache_raw_get_unsigned (regcache,
+		      loongarch_decode_imm ("0:5", insn, 0));
+      if (rj < rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x6c000000)		/* bgeu	rj, rd, offs16  */
+    {
+      ULONGEST rj = regcache_raw_get_unsigned (regcache,
+		      loongarch_decode_imm ("5:5", insn, 0));
+      ULONGEST rd = regcache_raw_get_unsigned (regcache,
+		      loongarch_decode_imm ("0:5", insn, 0));
+      if (rj >= rd)
+	next_pc = cur_pc + loongarch_decode_imm ("10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x40000000)		/* beqz	rj, offs21  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      if (rj == 0)
+	next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+    }
+  else if ((insn & 0xfc000000) == 0x44000000)		/* bnez	rj, offs21  */
+    {
+      LONGEST rj = regcache_raw_get_signed (regcache,
+		     loongarch_decode_imm ("5:5", insn, 0));
+      if (rj != 0)
+	next_pc = cur_pc + loongarch_decode_imm ("0:5|10:16<<2", insn, 1);
+    }
+
+  return next_pc;
+}
+
+/* Implement the "software_single_step" gdbarch method  */
+
+static std::vector<CORE_ADDR>
+loongarch_software_single_step (struct regcache *regcache)
+{
+  CORE_ADDR cur_pc = regcache_read_pc (regcache);
+  insn_t insn = loongarch_fetch_instruction (cur_pc);
+  CORE_ADDR next_pc = loongarch_next_pc (regcache, cur_pc, insn);
+
+  return {next_pc};
+}
+
 /* Adjust the address downward (direction of stack growth) so that it
    is correctly aligned for a new stack frame.  */
 
@@ -461,6 +565,7 @@ loongarch_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_frame_align (gdbarch, loongarch_frame_align);
 
   /* Breakpoint manipulation.  */
+  set_gdbarch_software_single_step (gdbarch, loongarch_software_single_step);
   set_gdbarch_breakpoint_kind_from_pc (gdbarch, loongarch_breakpoint::kind_from_pc);
   set_gdbarch_sw_breakpoint_from_kind (gdbarch, loongarch_breakpoint::bp_from_kind);


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-02 14:46 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-02 14:46 [binutils-gdb] gdb: LoongArch: Implement the software_single_step gdbarch method Tiezhu Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).