From patchwork Mon Jun 27 14:49:48 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bhushan Attarde X-Patchwork-Id: 13399 Received: (qmail 17128 invoked by alias); 27 Jun 2016 14:51:35 -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 15443 invoked by uid 89); 27 Jun 2016 14:51:21 -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=chip, 0x8000, physical, Determine 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:15 +0000 Received: from hhmail02.hh.imgtec.org (unknown [10.100.10.20]) by Forcepoint Email with ESMTPS id CA3F38905EAF2 for ; Mon, 27 Jun 2016 15:51:07 +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:10 +0100 From: Bhushan Attarde To: CC: , , , , , Bhushan Attarde Subject: [PATCH 21/24] MIPSR6 support for GDB Date: Mon, 27 Jun 2016 20:19:48 +0530 Message-ID: <1467038991-6600-21-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 patch adds initial MIPS revision 6 support. gdb/ChangeLog: * mips-tdep.c (mips_read_fp_register_single): Add declaration. (is_mipsr6_isa, mips32_relative_offset21): New functions. (mips32_relative_offset26, mips32_blez_pc); Likewise. (is_add32bit_overflow, is_add64bit_overflow): Likewise. (mips32_instruction_is_compact_branch): Likewise. (is_ll_insn, is_sc_insn): Likewise. (LLSC_R6_OPCODE, LL_R6_FUNCT, LLE_FUNCT): New definitions. (LLD_R6_FUNCT, SC_R6_FUNCT, SCE_FUNCT, SCD_R6_FUNCT): Likewise. (mips32_next_pc): New mips64bitreg variable and handle compact branch instructions to determine next PC. (mips_deal_with_atomic_sequence): Replace opcode checks with new is_ll_insn and is_sc_insn functions. Add support for R6 compact instructions. (mips_about_to_return): Mask the hint and the jalr/jr bit. (mips32_stack_frame_destroyed_p): Add jrc. (gdb_print_insn_mips): Set dis-both-r5-and-r6 option. (gdb_print_insn_mips_n32, gdb_print_insn_mips_n64): Likewise. (mips32_instruction_has_delay_slot): Restructure the code and add BLEZ, BGTZ instructions. (b0s21_imm): New definition. include/ChangeLog: * opcode/mips.h (INSN2_CONVERTED_TO_COMPACT, INSN2_NEXT_NO_DS) New definitions. (ASE_MXU, ASE_DSPR3, ASE_VIRT_XPA, ASE_EVA_R6): Likewise. opcodes/ChangeLog: * micromips-opc.c (alt_isa): New variable (I36, I37, I69): New definitions. * mips-dis.c (is_isa_r6): New function. (parse_mips_dis_option): Handle dis-both-r5-and-r6 option and set alt_isa accordingly. --- gdb/mips-tdep.c | 499 +++++++++++++++++++++++++++++++++++++++++++----- include/opcode/mips.h | 13 ++ opcodes/micromips-opc.c | 3 + opcodes/mips-dis.c | 33 +++- 4 files changed, 493 insertions(+), 55 deletions(-) diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 14e3aa6..68e00ec 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -74,6 +74,9 @@ static int mips16_insn_at_pc_has_delay_slot (struct gdbarch *gdbarch, static void mips_print_float_info (struct gdbarch *, struct ui_file *, struct frame_info *, const char *); +static int mips_read_fp_register_single (struct frame_info *, int, + gdb_byte *); + /* A useful bit in the CP0 status register (MIPS_PS_REGNUM). */ /* This bit is set if we are emulating 32-bit FPRs on a 64-bit chip. */ #define ST0_FR (1 << 26) @@ -2388,6 +2391,17 @@ mips_fetch_instruction (struct gdbarch *gdbarch, return extract_unsigned_integer (buf, instlen, byte_order); } +/* Return one if the gdbarch is based on MIPS Release 6. */ + +static int +is_mipsr6_isa (struct gdbarch *gdbarch) +{ + const struct bfd_arch_info *info = gdbarch_bfd_arch_info (gdbarch); + + return (info->mach == bfd_mach_mipsisa32r6 + || info->mach == bfd_mach_mipsisa64r6); +} + /* These are the fields of 32 bit mips instructions. */ #define mips32_op(x) (x >> 26) #define itype_op(x) (x >> 26) @@ -2430,6 +2444,7 @@ mips_fetch_instruction (struct gdbarch *gdbarch, #define b0s11_op(x) ((x) & 0x7ff) #define b0s12_imm(x) ((x) & 0xfff) #define b0s16_imm(x) ((x) & 0xffff) +#define b0s21_imm(x) ((x) & 0x1fffff) #define b0s26_imm(x) ((x) & 0x3ffffff) #define b6s10_ext(x) (((x) >> 6) & 0x3ff) #define b11s5_reg(x) (((x) >> 11) & 0x1f) @@ -2466,6 +2481,24 @@ mips32_relative_offset (ULONGEST inst) return ((itype_immediate (inst) ^ 0x8000) - 0x8000) << 2; } +/* Extract the 21-bit signed immediate offset from the MIPS instruction + INSN. */ + +static LONGEST +mips32_relative_offset21 (ULONGEST insn) +{ + return ((b0s21_imm (insn) ^ 0x100000) - 0x100000) << 2; +} + +/* Extract the 26-bit signed immediate offset from the MIPS instruction + INSN. */ + +static LONGEST +mips32_relative_offset26 (ULONGEST insn) +{ + return ((b0s26_imm (insn) ^ 0x2000000) - 0x2000000) << 2; +} + /* Determine the address of the next instruction executed after the INST floating condition branch instruction at PC. COUNT specifies the number of the floating condition bits tested by the branch. */ @@ -2590,6 +2623,53 @@ mips32_bc1_w_pc (struct gdbarch *gdbarch, struct frame_info *frame, return pc; } +/* Determine the address of the next instruction execute after the INST + BLEZ family of branch instructions at PC */ + +static CORE_ADDR +mips32_blez_pc (struct gdbarch *gdbarch, struct frame_info *frame, + ULONGEST inst, CORE_ADDR pc, int invert) +{ + int rs = itype_rs (inst); + int rt = itype_rt (inst); + LONGEST val_rs = get_frame_register_signed (frame, rs); + LONGEST val_rt = get_frame_register_signed (frame, rt); + 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; + + /* BLEZ, BLEZL, BGTZ, BGTZL */ + if (rt == 0) + { + delay_slot_size = 4; + taken = (val_rs <= 0); + } + else if (is_mipsr6_isa (gdbarch)) + { + /* BLEZALC, BGTZALC */ + if (rs == 0 && rt != 0) + taken = (val_rt <= 0); + /* BGEZALC, BLTZALC */ + else if (rs == rt && rt != 0) + taken = (val_rt >= 0); + /* BGEUC, BLTUC */ + else if (rs != rt && rs != 0 && rt != 0) + taken = (uval_rs >= uval_rt); + } + + if (invert) + taken = !taken; + + /* Calculate branch target */ + if (taken) + pc += mips32_relative_offset (inst); + else + pc += delay_slot_size; + + return pc; +} + /* Return nonzero if the gdbarch is an Octeon series. */ static int @@ -2618,6 +2698,24 @@ is_octeon_bbit_op (int op, struct gdbarch *gdbarch) return 0; } +/* Return 1 if A + B would overflow. */ + +static int +is_add32bit_overflow (int32_t a, int32_t b) +{ + int32_t r = (uint32_t) a + (uint32_t) b; + return (a < 0 && b < 0 && r >= 0) || (a >= 0 && b >= 0 && r < 0); +} + +static int +is_add64bit_overflow (int64_t a, int64_t b) +{ + if (a != (int32_t)a) + return 1; + if (b != (int32_t)b) + return 1; + return is_add32bit_overflow ((int32_t)a, (int32_t)b); +} /* Determine where to set a single step breakpoint while considering branch prediction. */ @@ -2628,12 +2726,18 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) struct gdbarch *gdbarch = get_frame_arch (frame); unsigned long inst; int op; + int mips64bitreg = 0; + + if (mips_isa_regsize (gdbarch) == 8) + mips64bitreg = 1; + inst = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL); op = itype_op (inst); if ((inst & 0xe0000000) != 0) /* Not a special, jump or branch instruction. */ { - if (op >> 2 == 5) + if (op >> 2 == 5 && ((op & 0x02) == 0 + || itype_rt (inst) == 0)) /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */ { switch (op & 0x03) @@ -2643,7 +2747,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) case 1: /* BNEL */ goto neq_branch; case 2: /* BLEZL */ - goto less_branch; + goto lez_branch; case 3: /* BGTZL */ goto greater_branch; default: @@ -2653,11 +2757,13 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) else if (op == 17 && itype_rs (inst) == 8) /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 1); - else if (op == 17 && itype_rs (inst) == 9 + else if (!is_mipsr6_isa (gdbarch) + && op == 17 && itype_rs (inst) == 9 && (itype_rt (inst) & 2) == 0) /* BC1ANY2F, BC1ANY2T: 010001 01001 xxx0x */ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 2); - else if (op == 17 && itype_rs (inst) == 10 + else if (!is_mipsr6_isa (gdbarch) + && op == 17 && itype_rs (inst) == 10 && (itype_rt (inst) & 2) == 0) /* BC1ANY4F, BC1ANY4T: 010001 01010 xxx0x */ pc = mips32_bc1_pc (gdbarch, frame, inst, pc + 4, 4); @@ -2669,7 +2775,7 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) /* BZ.V: 010001 01011 */ /* BNZ.V: 010001 01111 */ pc = mips32_bc1_w_pc (gdbarch, frame, inst, pc + 4); - else if (op == 29) + else if (!is_mipsr6_isa (gdbarch) && op == 29) /* JALX: 011101 */ /* The new PC will be alternate mode. */ { @@ -2697,7 +2803,114 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) else pc += 8; /* After the delay slot. */ } + else if (is_mipsr6_isa (gdbarch)) + { + /* BOVC, BEQZALC, BEQC and BNVC, BNEZALC, BNEC */ + if (op == 8 || op == 24) + { + int rs = rtype_rs (inst); + int rt = rtype_rt (inst); + LONGEST val_rs = get_frame_register_signed (frame, rs); + LONGEST val_rt = get_frame_register_signed (frame, rt); + int taken = 0; + /* BOVC (BNVC) */ + if (rs >= rt) + { + if (mips64bitreg == 1) + taken = is_add64bit_overflow (val_rs, val_rt); + else + taken = is_add32bit_overflow (val_rs, val_rt); + } + /* BEQZALC (BNEZALC) */ + else if (rs < rt && rs == 0) + taken = (val_rt == 0); + /* BEQC (BNEC) */ + else + taken = (val_rs == val_rt); + /* BNVC, BNEZALC, BNEC */ + if (op == 24) + taken = !taken; + + if (taken) + pc += mips32_relative_offset (inst) + 4; + else + pc += 4; + } + /* BC1EQZ, BC1NEZ */ + else if (op == 17 && (itype_rs (inst) == 9 || itype_rs (inst) == 13)) + { + gdb_byte status; + gdb_byte true_val = 0; + gdb_byte *raw_buffer = alloca (sizeof (gdb_byte) * 8); + mips_read_fp_register_single (frame, itype_rt (inst) + + gdbarch_num_regs (gdbarch) + + mips_regnum (gdbarch)->fp0, + raw_buffer); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + status = *(raw_buffer + 3); + else + status = *(raw_buffer); + + if (itype_rs (inst) == 13) + true_val = 1; + + if ((status & 0x1) == true_val) + pc += mips32_relative_offset (inst) + 4; + else + pc += 8; + } + else if (op == 22 || op == 23) + /* BLEZC, BGEZC, BGEC, BGTZC, BLTZC, BLTC */ + { + int rs = rtype_rs (inst); + int rt = rtype_rt (inst); + LONGEST val_rs = get_frame_register_signed (frame, rs); + LONGEST val_rt = get_frame_register_signed (frame, rt); + int taken = 0; + /* The R5 rt == 0 case is handled above so we treat it as + an unknown instruction here for future ISA usage. */ + if (rs == 0 && rt != 0) + taken = (val_rt <= 0); + else if (rs == rt && rt != 0) + taken = (val_rt >= 0); + else if (rs != rt && rs != 0 && rt != 0) + taken = (val_rs >= val_rt); + + if (op == 23) + taken = !taken; + + if (taken) + pc += mips32_relative_offset (inst) + 4; + else + pc += 4; + } + else if (op == 50 || op == 58) + /* BC, BALC */ + pc += mips32_relative_offset26 (inst) + 4; + else if ((op == 54 || op == 62) + && rtype_rs (inst) == 0) + /* JIC, JIALC */ + { + pc = get_frame_register_signed (frame, itype_rt (inst)); + pc += (itype_immediate (inst) ^ 0x8000) - 0x8000; + } + else if (op == 54 || op == 62) + /* BEQZC, BNEZC */ + { + int rs = itype_rs (inst); + LONGEST rs_val = get_frame_register_signed (frame, rs); + int taken = (rs_val == 0); + if (op == 62) + taken = !taken; + if (taken) + pc += mips32_relative_offset21 (inst) + 4; + else + pc += 4; + } + else + pc += 4; /* Not a branch, next instruction is easy. */ + } else pc += 4; /* Not a branch, next instruction is easy. */ } @@ -2757,22 +2970,32 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) pc += 8; /* after the delay slot */ break; case 0x1c: /* BPOSGE32 */ + case 0x18: /* BPOSGE32C */ case 0x1e: /* BPOSGE64 */ pc += 4; if (itype_rs (inst) == 0) { unsigned int pos = (op & 2) ? 64 : 32; int dspctl = mips_regnum (gdbarch)->dspctl; + int delay_slot_size = 4; if (dspctl == -1) /* No way to handle; it'll most likely trap anyway. */ break; + /* BPOSGE32C */ + if (op == 0x18) + { + if (!is_mipsr6_isa (gdbarch)) + break; + delay_slot_size = 0; + } + if ((get_frame_register_unsigned (frame, dspctl) & 0x7f) >= pos) pc += mips32_relative_offset (inst); else - pc += 4; + pc += delay_slot_size; } break; /* All of the other instructions in the REGIMM category */ @@ -2806,19 +3029,14 @@ mips32_next_pc (struct frame_info *frame, CORE_ADDR pc) else pc += 8; break; - case 6: /* BLEZ, BLEZL */ - if (get_frame_register_signed (frame, itype_rs (inst)) <= 0) - pc += mips32_relative_offset (inst) + 4; - else - pc += 8; + case 6: /* BLEZ, BLEZL, BLEZALC, BGEZALC, BGEUC */ + lez_branch: + pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 0); break; case 7: default: - greater_branch: /* BGTZ, BGTZL */ - if (get_frame_register_signed (frame, itype_rs (inst)) > 0) - pc += mips32_relative_offset (inst) + 4; - else - pc += 8; + greater_branch: /* BGTZ, BGTZL, BGTZALC, BLTZALC, BLTUC */ + pc = mips32_blez_pc (gdbarch, frame, inst, pc + 4, 1); break; } /* switch */ } /* else */ @@ -3456,6 +3674,46 @@ micromips_instruction_is_compact_branch (unsigned short insn) } } +/* Return non-zero if the MIPS instruction INSN is a compact branch + or jump. */ + +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: + /* BEQZC, JIC */ + case 54: + /* BNEZC, JIALC */ + case 62: + return is_mipsr6_isa (gdbarch); + /* BLEZC, BGEZC, BGEC */ + case 22: + /* BGTZC, BLTZC, BLTC */ + case 23: + /* BLEZALC, BGEZALC, BGEUC */ + case 6: + /* BGTZALC, BLTZALC, BLTUC */ + case 7: + return (is_mipsr6_isa (gdbarch) + && itype_rt (insn) != 0); + /* BPOSGE32C */ + case 1: + return (is_mipsr6_isa (gdbarch) + && itype_rt (insn) == 0x18 && itype_rs (insn) == 0); + default: + return 0; + } +} + struct mips_frame_cache { CORE_ADDR base; @@ -4503,7 +4761,8 @@ restart: reg = high_word & 0x1f; if (high_word == 0x27bd /* addiu $sp,$sp,-i */ - || high_word == 0x23bd /* addi $sp,$sp,-i */ + || (high_word == 0x23bd /* addi $sp,$sp,-i */ + && !is_mipsr6_isa (gdbarch)) || high_word == 0x67bd) /* daddiu $sp,$sp,-i */ { if (offset < 0) /* Negative stack adjustment? */ @@ -4638,7 +4897,8 @@ restart: /* A jump or branch, or enough non-prologue insns seen? If so, then we must have reached the end of the prologue by now. */ - if (prev_delay_slot || non_prologue_insns > 1) + if (prev_delay_slot || non_prologue_insns > 1 + || mips32_instruction_is_compact_branch (gdbarch, inst)) break; prev_non_prologue_insn = this_non_prologue_insn; @@ -4944,6 +5204,60 @@ mips_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR addr) #define LLD_OPCODE 0x34 #define SC_OPCODE 0x38 #define SCD_OPCODE 0x3c +#define LLSC_R6_OPCODE 0x1f +#define LL_R6_FUNCT 0x36 +#define LLE_FUNCT 0x2e +#define LLD_R6_FUNCT 0x37 +#define SC_R6_FUNCT 0x26 +#define SCE_FUNCT 0x1e +#define SCD_R6_FUNCT 0x27 + +static int +is_ll_insn (struct gdbarch *gdbarch, ULONGEST insn) +{ + if (itype_op (insn) == LL_OPCODE + || itype_op (insn) == LLD_OPCODE) + return 1; + + if (rtype_op (insn) == LLSC_R6_OPCODE + && rtype_funct (insn) == LLE_FUNCT + && (insn & 0x40) == 0) + return 1; + + /* Handle LL and LLX varieties. */ + if (is_mipsr6_isa (gdbarch) + && rtype_op (insn) == LLSC_R6_OPCODE + && (rtype_funct (insn) == LL_R6_FUNCT + || rtype_funct (insn) == LLD_R6_FUNCT + || rtype_funct (insn) == LLE_FUNCT)) + return 1; + + return 0; +} + +static int +is_sc_insn (struct gdbarch *gdbarch, ULONGEST insn) +{ + if (itype_op (insn) == SC_OPCODE + || itype_op (insn) == SCD_OPCODE) + return 1; + + if (rtype_op (insn) == LLSC_R6_OPCODE + && rtype_funct (insn) == SCE_FUNCT + && (insn & 0x40) == 0) + return 1; + + /* Handle SC and NOT SCX. The SCX must come first so we + do not want to prematurely end the sequence. */ + if (is_mipsr6_isa (gdbarch) + && rtype_op (insn) == LLSC_R6_OPCODE + && (rtype_funct (insn) == SC_R6_FUNCT + || rtype_funct (insn) == SCD_R6_FUNCT) + && (insn & 0x40) == 0) + return 1; + + return 0; +} static int mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, @@ -4957,10 +5271,11 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, int index; int last_breakpoint = 0; /* Defaults to 0 (no breakpoints placed). */ const int atomic_sequence_length = 16; /* Instruction sequence length. */ + int is_mipsr6 = is_mipsr6_isa (gdbarch); insn = mips_fetch_instruction (gdbarch, ISA_MIPS, loc, NULL); /* Assume all atomic sequences start with a ll/lld instruction. */ - if (itype_op (insn) != LL_OPCODE && itype_op (insn) != LLD_OPCODE) + if (!is_ll_insn (gdbarch, insn)) return 0; /* Assume that no atomic sequence is longer than "atomic_sequence_length" @@ -4990,16 +5305,49 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, return 0; /* fallback to the standard single-step code. */ case 4: /* BEQ */ case 5: /* BNE */ - case 6: /* BLEZ */ - case 7: /* BGTZ */ case 20: /* BEQL */ case 21: /* BNEL */ - case 22: /* BLEZL */ - case 23: /* BGTTL */ + case 22: /* BLEZL (BLEZC, BGEZC, BGEC) */ + case 23: /* BGTZL (BGTZC, BLTZC, BLTC) */ + is_branch = 1; + break; + case 6: /* BLEZ (BLEZALC, BGEZALC, BGEUC) */ + case 7: /* BGTZ (BGTZALC, BLTZALC, BLTUC) */ + if (is_mipsr6) + { + /* BLEZALC, BGTZALC */ + if (itype_rs (insn) == 0 && itype_rt (insn) != 0) + return 0; /* fallback to the standard single-step code. */ + /* BGEZALC, BLTZALC */ + else if (itype_rs (insn) == itype_rt (insn) + && itype_rt (insn) != 0) + return 0; /* fallback to the standard single-step code. */ + } is_branch = 1; break; + case 8: /* BOVC, BEQZALC, BEQC */ + case 24: /* BNVC, BNEZALC, BNEC */ + if (is_mipsr6) + is_branch = 1; + break; + case 50: /* BC */ + case 58: /* BALC */ + if (is_mipsr6) + return 0; /* fallback to the standard single-step code. */ + break; + case 54: /* BEQZC, JIC */ + case 62: /* BNEZC, JIALC */ + if (is_mipsr6) + { + if (itype_rs (insn) == 0) /* JIC, JIALC */ + return 0; /* fallback to the standard single-step code. */ + else + is_branch = 2; /* Marker for branches with a 21-bit offset */ + } + break; case 17: /* COP1 */ - is_branch = (((itype_rs (insn) == 9 || itype_rs (insn) == 10) + is_branch = ((!is_mipsr6 + && (itype_rs (insn) == 9 || itype_rs (insn) == 10) && (itype_rt (insn) & 0x2) == 0) /* BC1ANY2F, BC1ANY2T, BC1ANY4F, BC1ANY4T */ || (itype_rs (insn) & 0x18) == 0x18 @@ -5013,12 +5361,21 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, /* Fall through. */ case 18: /* COP2 */ case 19: /* COP3 */ - is_branch = (itype_rs (insn) == 8); /* BCzF, BCzFL, BCzT, BCzTL */ + /* BCzF, BCzFL, BCzT, BCzTL, BC*EQZ, BC*NEZ */ + is_branch = (itype_rs (insn) == 8) + || (is_mipsr6 + && itype_op (insn) != 19 + && (itype_rs (insn) == 9 + || itype_rs (insn) == 13)); break; } if (is_branch) { - branch_bp = loc + mips32_relative_offset (insn) + 4; + /* Is this a special PC21_S2 branch? */ + if (is_branch == 2) + branch_bp = loc + mips32_relative_offset21 (insn) + 4; + else + branch_bp = loc + mips32_relative_offset (insn) + 4; if (last_breakpoint >= 1) return 0; /* More than one branch found, fallback to the standard single-step code. */ @@ -5026,12 +5383,12 @@ mips_deal_with_atomic_sequence (struct gdbarch *gdbarch, last_breakpoint++; } - if (itype_op (insn) == SC_OPCODE || itype_op (insn) == SCD_OPCODE) + if (is_sc_insn (gdbarch, insn)) break; } /* Assume that the atomic sequence ends with a sc/scd instruction. */ - if (itype_op (insn) != SC_OPCODE && itype_op (insn) != SCD_OPCODE) + if (!is_sc_insn (gdbarch, insn)) return 0; loc += MIPS_INSN32_SIZE; @@ -5265,8 +5622,14 @@ mips_about_to_return (struct gdbarch *gdbarch, CORE_ADDR pc) gdb_assert (mips_pc_is_mips (pc)); insn = mips_fetch_instruction (gdbarch, ISA_MIPS, pc, NULL); - hint = 0x7c0; - return (insn & ~hint) == 0x3e00008; /* jr(.hb) $ra */ + /* Mask the hint and the jalr/jr bit */ + hint = 0x7c1; + + if (is_mipsr6_isa (gdbarch) && insn == 0xd81f0000) /* jrc $31 */ + return 1; + + /* jr(.hb) $ra and "jalr(.hb) $ra" */ + return ((insn & ~hint) == 0x3e00008); } @@ -7895,7 +8258,9 @@ mips32_stack_frame_destroyed_p (struct gdbarch *gdbarch, CORE_ADDR pc) if (high_word != 0x27bd /* addiu $sp,$sp,offset */ && high_word != 0x67bd /* daddiu $sp,$sp,offset */ - && inst != 0x03e00008 /* jr $ra */ + && (inst & ~0x1) != 0x03e00008 /* jr $31 or jalr $0, $31 */ + && (!is_mipsr6_isa (gdbarch) + || inst != 0xd81f0000) /* jrc $31 */ && inst != 0x00000000) /* nop */ return 0; } @@ -8220,12 +8585,17 @@ gdb_print_insn_mips (bfd_vma memaddr, struct disassemble_info *info) /* Set the disassembler options. */ if (!info->disassembler_options) + { /* This string is not recognized explicitly by the disassembler, but it tells the disassembler to not try to guess the ABI from the bfd elf headers, such that, if the user overrides the ABI of a program linked as NewABI, the disassembly will follow the register naming conventions specified by the user. */ - info->disassembler_options = "gpr-names=32"; + if (is_mipsr6_isa (gdbarch)) + info->disassembler_options = "gpr-names=32,dis-both-r5-and-r6=1"; + else + info->disassembler_options = "gpr-names=32"; + } /* Call the appropriate disassembler based on the target endian-ness. */ if (info->endian == BFD_ENDIAN_BIG) @@ -8239,7 +8609,10 @@ gdb_print_insn_mips_n32 (bfd_vma memaddr, struct disassemble_info *info) { /* Set up the disassembler info, so that we get the right register names from libopcodes. */ - info->disassembler_options = "gpr-names=n32"; + if (is_mipsr6_isa (info->application_data)) + info->disassembler_options = "gpr-names=n32,dis-both-r5-and-r6=1"; + else + info->disassembler_options = "gpr-names=n32"; info->flavour = bfd_target_elf_flavour; return gdb_print_insn_mips (memaddr, info); @@ -8250,7 +8623,10 @@ gdb_print_insn_mips_n64 (bfd_vma memaddr, struct disassemble_info *info) { /* Set up the disassembler info, so that we get the right register names from libopcodes. */ - info->disassembler_options = "gpr-names=64"; + if (is_mipsr6_isa (info->application_data)) + info->disassembler_options = "gpr-names=64,dis-both-r5-and-r6=1"; + else + info->disassembler_options = "gpr-names=64"; info->flavour = bfd_target_elf_flavour; return gdb_print_insn_mips (memaddr, info); @@ -8416,22 +8792,37 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst) { rs = itype_rs (inst); rt = itype_rt (inst); - return (is_octeon_bbit_op (op, gdbarch) - || op >> 2 == 5 /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */ - || op == 29 /* JALX: bits 011101 */ - || (op == 17 - && (rs == 8 - /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */ - || (rs == 9 && (rt & 0x2) == 0) - /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */ - || (rs == 10 && (rt & 0x2) == 0) - /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */ - || ((rs & 0x18) == 0x18) - /* BZ.df: bits 010001 110xx */ - /* BNZ.df: bits 010001 111xx */ - || ((rs & 0x1b) == 0x0b)))); - /* BZ.V: bits 010001 01011 */ - /* BNZ.V: bits 010001 01111 */ + if (is_octeon_bbit_op (op, gdbarch) + || (op >> 1 == 10) /* BEQL, BNEL: bits 01010x */ + || (op >> 1 == 11 && rt == 0) /* BLEZL, BGTZL: bits 01011x */ + || (!is_mipsr6_isa (gdbarch) && op == 29)) /* JALX: bits 011101 */ + return 1; + else if (op == 17) /* COP1 */ + { + if (rs == 8 /* BC1F, BC1FL, BC1T, BC1TL: 010001 01000 */ + || ((rs & 0x18) == 0x18) /* BZ.df: bits 010001 110xx */ + /* BNZ.df: bits 010001 111xx */ + || ((rs & 0x1b) == 0x0b)) /* BZ.V: bits 010001 01011 */ + /* BNZ.V: bits 010001 01111 */ + return 1; + else if (!is_mipsr6_isa (gdbarch) + /* BC1ANY2F, BC1ANY2T: bits 010001 01001 */ + && ((rs == 9 && (rt & 0x2) == 0) + /* BC1ANY4F, BC1ANY4T: bits 010001 01010 */ + || (rs == 10 && (rt & 0x2) == 0))) + return 1; + else if (is_mipsr6_isa (gdbarch) + && (rs == 9 /* BC1EQZ: 010001 01001 */ + || rs == 13)) /* BC1NEZ: 010001 01101 */ + return 1; + } + else if (op == 18) /* COP2 */ + { + if (is_mipsr6_isa (gdbarch) + && (rs == 9 /* BC2EQZ: 010010 01001 */ + || rs == 13)) /* BC2NEZ: 010010 01101 */ + return 1; + } } else switch (op & 0x07) /* extract bits 28,27,26 */ @@ -8450,7 +8841,11 @@ mips32_instruction_has_delay_slot (struct gdbarch *gdbarch, ULONGEST inst) || ((rt & 0x1e) == 0x1c && rs == 0)); /* BPOSGE32, BPOSGE64: bits 1110x */ break; /* end REGIMM */ - default: /* J, JAL, BEQ, BNE, BLEZ, BGTZ */ + case 6: /* BLEZ */ + case 7: /* BGTZ */ + return (itype_rt (inst) == 0); + break; + default: /* J, JAL, BEQ, BNE */ return 1; break; } @@ -9103,6 +9498,8 @@ mips_in_return_stub (struct gdbarch *gdbarch, CORE_ADDR pc, const char *name) PC of the stub target. The stub just loads $t9 and jumps to it, so that $t9 has the correct value at function entry. */ +/* TODO: Update for compact jump trampoline */ + static CORE_ADDR mips_skip_pic_trampoline_code (struct frame_info *frame, CORE_ADDR pc) { diff --git a/include/opcode/mips.h b/include/opcode/mips.h index 88bf8f8..eace840 100644 --- a/include/opcode/mips.h +++ b/include/opcode/mips.h @@ -1102,6 +1102,10 @@ struct mips_opcode #define INSN2_VU0_CHANNEL_SUFFIX 0x00004000 /* Instruction has a forbidden slot. */ #define INSN2_FORBIDDEN_SLOT 0x00008000 +/* This indicates pre-R6 instructions mapped to R6 ones. */ +#define INSN2_CONVERTED_TO_COMPACT 0x00010000 +/* Instruction prevents the following instruction from being in a DS */ +#define INSN2_NEXT_NO_DS 0x00020000 /* Masks used to mark instructions to indicate which MIPS ISA level they were introduced in. INSN_ISA_MASK masks an enumeration that @@ -1256,6 +1260,15 @@ static const unsigned int mips_isa_table[] = { #define ASE_MSA64 0x00001000 /* eXtended Physical Address (XPA) Extension. */ #define ASE_XPA 0x00002000 +/* MXU Extension. */ +#define ASE_MXU 0x00004000 +#define ASE_DSPR3 0x00008000 +/* The Virtualization ASE has eXtended Physical Address (XPA) Extension + instructions which are only valid when both ASEs are enabled. */ +#define ASE_VIRT_XPA 0x00010000 +/* The eXtended Physical Address (XPA) Extension has instructions which are + only valid for the r6 ISA. */ +#define ASE_EVA_R6 0x00020000 /* MIPS ISA defines, use instead of hardcoding ISA level. */ diff --git a/opcodes/micromips-opc.c b/opcodes/micromips-opc.c index e182f47..ac7b6f7 100644 --- a/opcodes/micromips-opc.c +++ b/opcodes/micromips-opc.c @@ -253,6 +253,9 @@ decode_micromips_operand (const char *p) are accepted as 64-bit microMIPS ISA. */ #define I1 INSN_ISA1 #define I3 INSN_ISA3 +#define I36 INSN_ISA32R5 +#define I37 INSN_ISA32R6 +#define I69 INSN_ISA64R6 /* MIPS DSP ASE support. */ #define WR_a WR_HILO /* Write DSP accumulators (reuse WR_HILO). */ diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index e152876..94bd369 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -668,6 +668,7 @@ const struct mips_arch_choice mips_arch_choices[] = values. */ static int mips_processor; static int mips_isa; +static int alt_isa = -1; static int mips_ase; static int micromips_ase; static const char * const *mips_gpr_names; @@ -764,6 +765,17 @@ is_micromips (Elf_Internal_Ehdr *header) return 0; } +/* Check if ISA is R6. */ + +static inline int +is_isa_r6 (unsigned long isa) +{ + if ((isa & INSN_ISA_MASK) == ISA_MIPS32R6 + || ((isa & INSN_ISA_MASK) == ISA_MIPS64R6)) + return 1; + return 0; +} + static void set_default_mips_dis_options (struct disassemble_info *info) { @@ -836,6 +848,17 @@ parse_mips_dis_option (const char *option, unsigned int len) return; } + if (CONST_STRNEQ (option, "dis-both-r5-and-r6")) + { + if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6) + alt_isa = ISA_MIPS32R5; + else if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6) + alt_isa = ISA_MIPS64R5; + else + alt_isa = -1; + return; + } + if (CONST_STRNEQ (option, "msa")) { mips_ase |= ASE_MSA; @@ -1702,10 +1725,12 @@ print_insn_mips (bfd_vma memaddr, && (word & op->mask) == op->match) { /* We always disassemble the jalx instruction, except for MIPS r6. */ - if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor) - && (strcmp (op->name, "jalx") - || (mips_isa & INSN_ISA_MASK) == ISA_MIPS32R6 - || (mips_isa & INSN_ISA_MASK) == ISA_MIPS64R6)) + if ((!opcode_is_member (op, mips_isa, mips_ase, mips_processor) + && (alt_isa == -1 + || !opcode_is_member (op, alt_isa, 0, 0)) + && (strcmp (op->name, "jalx") + || is_isa_r6 (mips_isa))) + || (op->pinfo2 & INSN2_CONVERTED_TO_COMPACT)) continue; /* Figure out instruction type and branch delay information. */