This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH 21/24] MIPSR6 support for GDB


    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.  */
-- 
1.9-rc2


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]