From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7873) id B54EB3851A8C; Mon, 13 Jun 2022 14:28:37 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B54EB3851A8C Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable From: Tiezhu Yang To: gdb-cvs@sourceware.org Subject: [binutils-gdb] gdb: LoongArch: Deal with atomic sequence X-Act-Checkin: binutils-gdb X-Git-Author: Tiezhu Yang X-Git-Refname: refs/heads/master X-Git-Oldrev: c714aff10b1a5542dac657d86eb56140945bbd65 X-Git-Newrev: 208b57e53ed98106d20c7314e88d0a7225a8aa1d Message-Id: <20220613142837.B54EB3851A8C@sourceware.org> Date: Mon, 13 Jun 2022 14:28:37 +0000 (GMT) X-BeenThere: gdb-cvs@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Jun 2022 14:28:37 -0000 https://sourceware.org/git/gitweb.cgi?p=3Dbinutils-gdb.git;h=3D208b57e53ed9= 8106d20c7314e88d0a7225a8aa1d commit 208b57e53ed98106d20c7314e88d0a7225a8aa1d Author: Tiezhu Yang Date: Mon Jun 13 09:55:11 2022 +0800 gdb: LoongArch: Deal with atomic sequence =20 We can't put a breakpoint in the middle of a ll/sc atomic sequence, so look for the end of the sequence and put the breakpoint there. =20 Signed-off-by: Tiezhu Yang Diff: --- gdb/loongarch-tdep.c | 127 +++++++++++++++++++++++++++++++++++++++++++++--= ---- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/gdb/loongarch-tdep.c b/gdb/loongarch-tdep.c index 963e832454a..e6b93a5cfce 100644 --- a/gdb/loongarch-tdep.c +++ b/gdb/loongarch-tdep.c @@ -45,22 +45,64 @@ loongarch_fetch_instruction (CORE_ADDR pc) return extract_unsigned_integer (buf, insn_len, BFD_ENDIAN_LITTLE); } =20 +/* Return TRUE if INSN is a unconditional branch instruction, otherwise re= turn FALSE. */ + +static bool +loongarch_insn_is_uncond_branch (insn_t insn) +{ + if ((insn & 0xfc000000) =3D=3D 0x4c000000 /* jirl */ + || (insn & 0xfc000000) =3D=3D 0x50000000 /* b */ + || (insn & 0xfc000000) =3D=3D 0x54000000) /* bl */ + return true; + return false; +} + +/* Return TRUE if INSN is a conditional branch instruction, otherwise retu= rn FALSE. */ + +static bool +loongarch_insn_is_cond_branch (insn_t insn) +{ + if ((insn & 0xfc000000) =3D=3D 0x58000000 /* beq */ + || (insn & 0xfc000000) =3D=3D 0x5c000000 /* bne */ + || (insn & 0xfc000000) =3D=3D 0x60000000 /* blt */ + || (insn & 0xfc000000) =3D=3D 0x64000000 /* bge */ + || (insn & 0xfc000000) =3D=3D 0x68000000 /* bltu */ + || (insn & 0xfc000000) =3D=3D 0x6c000000 /* bgeu */ + || (insn & 0xfc000000) =3D=3D 0x40000000 /* beqz */ + || (insn & 0xfc000000) =3D=3D 0x44000000) /* bnez */ + return true; + return false; +} + /* Return TRUE if INSN is a branch instruction, otherwise return FALSE. */ =20 static bool loongarch_insn_is_branch (insn_t insn) { - if ((insn & 0xfc000000) =3D=3D 0x4c000000 /* jirl rd, rj, offs16 = */ - || (insn & 0xfc000000) =3D=3D 0x50000000 /* b offs26 */ - || (insn & 0xfc000000) =3D=3D 0x54000000 /* bl offs26 */ - || (insn & 0xfc000000) =3D=3D 0x58000000 /* beq rj, rd, offs16 */ - || (insn & 0xfc000000) =3D=3D 0x5c000000 /* bne rj, rd, offs16 */ - || (insn & 0xfc000000) =3D=3D 0x60000000 /* blt rj, rd, offs16 */ - || (insn & 0xfc000000) =3D=3D 0x64000000 /* bge rj, rd, offs16 */ - || (insn & 0xfc000000) =3D=3D 0x68000000 /* bltu rj, rd, offs16 = */ - || (insn & 0xfc000000) =3D=3D 0x6c000000 /* bgeu rj, rd, offs16 = */ - || (insn & 0xfc000000) =3D=3D 0x40000000 /* beqz rj, offs21 */ - || (insn & 0xfc000000) =3D=3D 0x44000000) /* bnez rj, offs21 */ + bool is_uncond =3D loongarch_insn_is_uncond_branch (insn); + bool is_cond =3D loongarch_insn_is_cond_branch (insn); + + return (is_uncond || is_cond); +} + +/* Return TRUE if INSN is a Load Linked instruction, otherwise return FALS= E. */ + +static bool +loongarch_insn_is_ll (insn_t insn) +{ + if ((insn & 0xff000000) =3D=3D 0x20000000 /* ll.w */ + || (insn & 0xff000000) =3D=3D 0x22000000) /* ll.d */ + return true; + return false; +} + +/* Return TRUE if INSN is a Store Conditional instruction, otherwise retur= n FALSE. */ + +static bool +loongarch_insn_is_sc (insn_t insn) +{ + if ((insn & 0xff000000) =3D=3D 0x21000000 /* sc.w */ + || (insn & 0xff000000) =3D=3D 0x23000000) /* sc.d */ return true; return false; } @@ -182,8 +224,9 @@ loongarch_skip_prologue (struct gdbarch *gdbarch, CORE_= ADDR pc) next instruction. */ =20 static CORE_ADDR -loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc, insn_t ins= n) +loongarch_next_pc (struct regcache *regcache, CORE_ADDR cur_pc) { + insn_t insn =3D loongarch_fetch_instruction (cur_pc); size_t insn_len =3D loongarch_insn_length (insn); CORE_ADDR next_pc =3D cur_pc + insn_len; =20 @@ -270,14 +313,70 @@ loongarch_next_pc (struct regcache *regcache, CORE_AD= DR cur_pc, insn_t insn) return next_pc; } =20 +/* We can't put a breakpoint in the middle of a ll/sc atomic sequence, + so look for the end of the sequence and put the breakpoint there. */ + +static std::vector +loongarch_deal_with_atomic_sequence (struct regcache *regcache, CORE_ADDR = cur_pc) +{ + CORE_ADDR next_pc; + std::vector next_pcs; + insn_t insn =3D loongarch_fetch_instruction (cur_pc); + size_t insn_len =3D loongarch_insn_length (insn); + const int atomic_sequence_length =3D 16; + bool found_atomic_sequence_endpoint =3D false; + + /* Look for a Load Linked instruction which begins the atomic sequence. = */ + if (!loongarch_insn_is_ll (insn)) + return {}; + + /* Assume that no atomic sequence is longer than "atomic_sequence_length= " instructions. */ + for (int insn_count =3D 0; insn_count < atomic_sequence_length; ++insn_c= ount) + { + cur_pc +=3D insn_len; + insn =3D loongarch_fetch_instruction (cur_pc); + + /* Look for a unconditional branch instruction, fallback to the stan= dard code. */ + if (loongarch_insn_is_uncond_branch (insn)) + { + return {}; + } + /* Look for a conditional branch instruction, put a breakpoint in it= s destination address. */ + else if (loongarch_insn_is_cond_branch (insn)) + { + next_pc =3D loongarch_next_pc (regcache, cur_pc); + next_pcs.push_back (next_pc); + } + /* Look for a Store Conditional instruction which closes the atomic = sequence. */ + else if (loongarch_insn_is_sc (insn)) + { + found_atomic_sequence_endpoint =3D true; + next_pc =3D cur_pc + insn_len; + next_pcs.push_back (next_pc); + break; + } + } + + /* We didn't find a closing Store Conditional instruction, fallback to t= he standard code. */ + if (!found_atomic_sequence_endpoint) + return {}; + + return next_pcs; +} + /* Implement the "software_single_step" gdbarch method */ =20 static std::vector loongarch_software_single_step (struct regcache *regcache) { CORE_ADDR cur_pc =3D regcache_read_pc (regcache); - insn_t insn =3D loongarch_fetch_instruction (cur_pc); - CORE_ADDR next_pc =3D loongarch_next_pc (regcache, cur_pc, insn); + std::vector next_pcs + =3D loongarch_deal_with_atomic_sequence (regcache, cur_pc); + + if (!next_pcs.empty ()) + return next_pcs; + + CORE_ADDR next_pc =3D loongarch_next_pc (regcache, cur_pc); =20 return {next_pc}; }