[PATCH] RISC-V: Add software single step support for cm.popret[z]
Kito Cheng
kito.cheng@gmail.com
Thu May 15 09:18:35 GMT 2025
More information about the Binutils mailing list
Thu May 15 09:18:35 GMT 2025
- Previous message (by thread): [PATCH] RISC-V: Add software single step support for cm.popret[z]
- Next message (by thread): [patch, avr] PR32968: Assert that .progmem is located in the lower 64k
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
this should be send to gdb-patches@sourceware.org rather than binutils@sourceware.org On Thu, May 15, 2025 at 5:17 PM Songhe Zhu <zhusonghe@eswincomputing.com> wrote: > > From: zhusonghe <zhusonghe@eswincomputing.com> > > The Linux GDB build configures gdbarch_software_single_step_p() = 1, > indicating that software single-stepping is enabled while hardware > single-stepping is disabled. According to the RISC-V Zc Specification v1.0.4-3, > instructions like cm.popret[z] require precise control flow handling. > When single-stepping through these instructions, the Program Counter (PC) > must be explicitly updated to maintain correct execution flow. > > Passing riscv-gnu-toolchain regressions. > > Signed-off-by: Songhe Zhu <zhusonghe@eswincomputing.com> > Co-Authored by: Fei Gao <gaofei@eswincomputing.com> > > gdb/ChangeLog: > > * riscv-tdep.c (ROUND_UP): New. > (zcmp_base_adj): Compute stack_adj_base. > (zcmp_rlist_regcounts): Through reg_list, compute reg counts. > (class riscv_insn): Add support for cm.popret[z] opcodes. > (riscv_insn::decode): Ditto. > (riscv_next_pc): Add support cm.popret[z] function. > --- > gdb/riscv-tdep.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 54 insertions(+) > > diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c > index 8998a297315..fa9fef44723 100644 > --- a/gdb/riscv-tdep.c > +++ b/gdb/riscv-tdep.c > @@ -66,6 +66,9 @@ > /* The biggest alignment that the target supports. */ > #define BIGGEST_ALIGNMENT 16 > > +/* This macro rounds x up to the y boundary. */ > +#define ROUND_UP(x,y) (((x) + (y) - 1) & ~((y) - 1)) > + > /* Define a series of is_XXX_insn functions to check if the value INSN > is an instance of instruction XXX. */ > #define DECLARE_INSN(INSN_NAME, INSN_MATCH, INSN_MASK) \ > @@ -774,6 +777,20 @@ show_riscv_debug_variable (struct ui_file *file, int from_tty, > c->name, value); > } > > + > +static int > +zcmp_base_adj (int word_bytes, int regcounts) > +{ > + return ROUND_UP(word_bytes * regcounts, 16); > +} > + > + /* According to zcmp rlist field caculate register counts. */ > +static int > +zcmp_rlist_regcounts (int rlist) > +{ > + return (rlist == 15 ? rlist - 2 : rlist - 3); > +} > + > /* See riscv-tdep.h. */ > > int > @@ -1593,6 +1610,8 @@ class riscv_insn > BGE, > BLTU, > BGEU, > + CM_POPRET, > + CM_POPRETZ, > /* These are needed for stepping over atomic sequences. */ > SLTI, > SLTIU, > @@ -1691,6 +1710,12 @@ class riscv_insn > return ((opcode >> offset) & 0x7) + 8; > } > > + /* Extract 4 bit rlist field at OFFSET from instruction OPCODE. */ > + int decode_rlist (unsigned long opcode, int offset) > + { > + return (opcode >> offset) & 0xF; > + } > + > /* Helper for DECODE, decode 32-bit R-type instruction. */ > void decode_r_type_insn (enum opcode opcode, ULONGEST ival) > { > @@ -1822,6 +1847,13 @@ class riscv_insn > m_rs2 = decode_register_index_short (ival, OP_SH_CRS2S); > } > > + void decode_zcmp_type_insn (enum opcode opcode, ULONGEST ival) > + { > + m_opcode = opcode; > + m_rs1 = decode_rlist (ival, OP_SH_REG_LIST); > + m_imm.s = EXTRACT_ZCMP_SPIMM (ival); > + } > + > /* The length of the instruction in bytes. Should be 2 or 4. */ > int m_length; > > @@ -2091,6 +2123,10 @@ riscv_insn::decode (struct gdbarch *gdbarch, CORE_ADDR pc) > decode_ci_type_insn (LD, ival, RISCV_SP_REGNUM); > else if (is_c_lwsp_insn (ival)) > decode_ci_type_insn (LW, ival, RISCV_SP_REGNUM); > + else if (is_cm_popret_insn (ival)) > + decode_zcmp_type_insn (CM_POPRET, ival); > + else if (is_cm_popretz_insn (ival)) > + decode_zcmp_type_insn (CM_POPRETZ, ival); > else > /* None of the other fields of INSN are valid in this case. */ > m_opcode = OTHER; > @@ -4523,6 +4559,24 @@ riscv_next_pc (struct regcache *regcache, CORE_ADDR pc) > if (tdep->syscall_next_pc != nullptr) > next_pc = tdep->syscall_next_pc (get_current_frame ()); > } > + else if ((insn.opcode () == riscv_insn::CM_POPRET) > + || (insn.opcode () == riscv_insn::CM_POPRETZ)) > + { > + LONGEST sp; > + gdb_byte buf[8]; > + int isa_xlen = riscv_isa_xlen (gdbarch); > + int regcounts = zcmp_rlist_regcounts (insn.rs1 ()); > + int stack_adj_base = zcmp_base_adj (isa_xlen, regcounts); > + int stack_adj = stack_adj_base + insn.imm_signed (); > + regcache->cooked_read (RISCV_SP_REGNUM, &sp); > + enum bfd_endian byte_order = gdbarch_byte_order_for_code (gdbarch); > + CORE_ADDR ra_addr = sp + stack_adj - isa_xlen * regcounts; > + int status = target_read_memory (ra_addr, buf, isa_xlen); > + if (status) > + memory_error (TARGET_XFER_E_IO, ra_addr); > + ULONGEST ra_value = extract_unsigned_integer (buf, isa_xlen, byte_order); > + next_pc = (ra_value) & ~(CORE_ADDR) 0x1; > + } > > return next_pc; > } > -- > 2.17.1 >
- Previous message (by thread): [PATCH] RISC-V: Add software single step support for cm.popret[z]
- Next message (by thread): [patch, avr] PR32968: Assert that .progmem is located in the lower 64k
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Binutils mailing list