From patchwork Mon Jun 27 14:49:51 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 13402 Received: (qmail 17761 invoked by alias); 27 Jun 2016 14:51:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 16182 invoked by uid 89); 27 Jun 2016 14:51:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=3.8 required=5.0 tests=AWL, BAYES_00, GARBLED_SUBJECT, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, SPF_PASS autolearn=no version=3.3.2 spammy=jumped, forbidden X-HELO: mailapp01.imgtec.com Received: from mailapp01.imgtec.com (HELO mailapp01.imgtec.com) (195.59.15.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 27 Jun 2016 14:51:25 +0000 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id 77D57F56DC7BC for ; Mon, 27 Jun 2016 15:51:18 +0100 (IST) Received: from pudesk170.pu.imgtec.org (192.168.93.65) by hhmail02.hh.imgtec.org (10.100.10.20) with Microsoft SMTP Server (TLS) id 14.3.294.0; Mon, 27 Jun 2016 15:51:21 +0100 From: Bhushan Attarde To: CC: , , , , , Bhushan Attarde Subject: [PATCH 24/24] MIPS R6 forbidden slot support Date: Mon, 27 Jun 2016 20:19:51 +0530 Message-ID: <1467038991-6600-24-git-send-email-bhushan.attarde@imgtec.com> In-Reply-To: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> References: <1467038991-6600-1-git-send-email-bhushan.attarde@imgtec.com> MIME-Version: 1.0 This approach leads to single step skipping forbidden slots. It also means that breakpoints cannot be set on forbidden slots and are instead moved to the next instruction. gdb/ChangeLog: * mips-tdep.c (mips32_next_pc): Step through the forbidden slot. (mips32_instruction_is_compact_branch): Add R6 compact branch instructions. (mips32_insn_at_pc_has_forbidden_slot): New function. (mips_adjust_breakpoint_address): Update comment and adjust breakpoint address in case of conditional compact branch instructions. --- gdb/mips-tdep.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 88 insertions(+), 18 deletions(-) diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index d5dd668..50f7bac 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -2637,7 +2637,7 @@ mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame, ULONGEST uval_rs = get_frame_register_unsigned (frame, rs); ULONGEST uval_rt = get_frame_register_unsigned (frame, rt); int taken = 0; - int delay_slot_size = 0; + int delay_slot_size = 4; /* BLEZ, BLEZL, BGTZ, BGTZL */ if (rt == 0) @@ -2656,6 +2656,12 @@ mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame, /* BGEUC, BLTUC */ else if (rs != rt && rs != 0 && rt != 0) taken = (uval_rs >= uval_rt); + + /* Step through the forbidden slot to avoid repeated exceptions we do + not currently have access to the BD bit when hitting a breakpoint + and therefore cannot tell if the breakpoint hit on the branch or the + forbidden slot. */ + /* delay_slot_size = 0; */ } if (invert) @@ -2835,7 +2841,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) if (taken) pc += mips32_relative_offset (inst) + 4; else - pc += 4; + /* Step through the forbidden slot to avoid repeated exceptions + we do not currently have access to the BD bit when hitting a + breakpoint and therefore cannot tell if the breakpoint + hit on the branch or the forbidden slot. */ + pc += 8; } /* BC1EQZ, BC1NEZ */ else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13)) @@ -2883,7 +2893,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) if (taken) pc += mips32_relative_offset (inst) + 4; else - pc += 4; + /* Step through the forbidden slot to avoid repeated exceptions + we do not currently have access to the BD bit when hitting a + breakpoint and therefore cannot tell if the breakpoint + hit on the branch or the forbidden slot. */ + pc += 8; } else if (op == 50 || op == 58) /* BC, BALC */ @@ -2906,7 +2920,11 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) if (taken) pc += mips32_relative_offset21 (inst) + 4; else - pc += 4; + /* Step through the forbidden slot to avoid repeated exceptions + we do not currently have access to the BD bit when hitting a + breakpoint and therefore cannot tell if the breakpoint + hit on the branch or the forbidden slot. */ + pc += 8; } else pc += 4; /* Not a branch, next instruction is easy. */ @@ -2988,7 +3006,13 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) { if (!is_mipsr6_isa (gdbarch)) break; - delay_slot_size = 0; + + /* Step through the forbidden slot to avoid repeated + exceptions we do not currently have access to the BD + bit when hitting a breakpoint and therefore cannot + tell if the breakpoint hit on the branch or the + forbidden slot. */ + /* delay_slot_size = 0; */ } if ((get_frame_register_unsigned (frame, @@ -3675,26 +3699,36 @@ micromips_instruction_is_compact_branch (unsigned short insn) } /* Return non-zero if the MIPS instruction INSN is a compact branch - or jump. */ + or jump. A value of 1 indicates an unconditional compact branch + and a value of 2 indicates a conditional compact branch. */ static int mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn) { switch (itype_op (insn)) { - /* BOVC, BEQZALC, BEQC */ - case 8: - /* BNVC, BNEZALC, BNEC */ - case 24: /* BC */ case 50: /* BALC */ case 58: + if (is_mipsr6_isa (gdbarch)) + return 1; + break; + /* BOVC, BEQZALC, BEQC */ + case 8: + /* BNVC, BNEZALC, BNEC */ + case 24: + if (is_mipsr6_isa (gdbarch)) + return 2; + break; /* BEQZC, JIC */ case 54: /* BNEZC, JIALC */ case 62: - return is_mipsr6_isa (gdbarch); + if (is_mipsr6_isa (gdbarch)) + /* JIC, JIALC are unconditional */ + return (itype_rs (insn) == 0) ? 1 : 2; + break; /* BLEZC, BGEZC, BGEC */ case 22: /* BGTZC, BLTZC, BLTC */ @@ -3703,15 +3737,33 @@ mips32_instruction_is_compact_branch (struct gdbarch *gdbarch, ULONGEST insn) case 6: /* BGTZALC, BLTZALC, BLTUC */ case 7: - return (is_mipsr6_isa (gdbarch) - && itype_rt (insn) != 0); + if (is_mipsr6_isa (gdbarch) + && itype_rt (insn) != 0) + return 2; + break; /* BPOSGE32C */ case 1: - return (is_mipsr6_isa (gdbarch) - && itype_rt (insn) == 0x18 && itype_rs (insn) == 0); - default: - return 0; + if (is_mipsr6_isa (gdbarch) + && itype_rt (insn) == 0x18 && itype_rs (insn) == 0) + return 2; } + return 0; +} + +/* Return non-zero if a standard MIPS instruction at ADDR has a branch + forbidden slot (i.e. it is a conditional compact branch instruction). */ + +static int +mips32_insn_at_pc_has_forbidden_slot (struct gdbarch *gdbarch, CORE_ADDR addr) +{ + ULONGEST insn; + int status; + + insn = mips_fetch_instruction (gdbarch, ISA_MIPS, addr, &status); + if (status) + return 0; + + return mips32_instruction_is_compact_branch (gdbarch, insn) == 2; } struct mips_frame_cache @@ -9064,7 +9116,18 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) So, we'll use the second solution. To do this we need to know if the instruction we're trying to set the breakpoint on is in the - branch delay slot. */ + branch delay slot. + + A similar problem occurs for breakpoints on forbidden slots where + the trap will be reported for the branch with the BD bit set. + In this case it would be ideal to recover using solution 1 from + above as there is no problem with the branch being skipped + (since the forbidden slot only exists on not-taken branches). + However, the BD bit is not available in all scenarios currently + so instead we move the breakpoint on to the next instruction. + This means that it is not possible to stop on an instruction + that can be in a forbidden slot even if that instruction is + jumped to directly. */ boundary = mips_segment_boundary (bpaddr); @@ -9086,6 +9149,13 @@ mips_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr) prev_addr = bpaddr - 4; if (mips32_insn_at_pc_has_delay_slot (gdbarch, prev_addr)) bpaddr = prev_addr; + /* If the previous instruction has a forbidden slot, we have to + move the breakpoint to the following instruction to prevent + breakpoints in forbidden slots being reported as unknown + traps. */ + else if (mips32_insn_at_pc_has_forbidden_slot (gdbarch, prev_addr)) + + bpaddr += 4; } else {