2013-10-14 Chao-ying Fu <Chao-ying.Fu@imgtec.com>
[deliverable/binutils-gdb.git] / opcodes / mips-dis.c
index 03333bfd9546171d3d3890bdfc28c4fc7d3c7157..72f307f2f5130ec9fa4c088ac613d1a0cff8641a 100644 (file)
@@ -401,6 +401,15 @@ static const char * const mips_hwr_names_mips3264r2[32] =
   "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
 };
 
+static const char * const msa_control_names[32] =
+{
+  "msa_ir",    "msa_csr",      "msa_access",   "msa_save",
+  "msa_modify",        "msa_request",  "msa_map",      "msa_unmap",
+  "$8",   "$9",   "$10",  "$11",  "$12",  "$13",  "$14",  "$15",
+  "$16",  "$17",  "$18",  "$19",  "$20",  "$21",  "$22",  "$23",
+  "$24",  "$25",  "$26",  "$27",  "$28",  "$29",  "$30",  "$31"
+};
+
 struct mips_abi_choice
 {
   const char * name;
@@ -498,7 +507,7 @@ const struct mips_arch_choice mips_arch_choices[] =
   { "mips32r2",        1, bfd_mach_mipsisa32r2, CPU_MIPS32R2,
     ISA_MIPS32R2,
     (ASE_SMARTMIPS | ASE_DSP | ASE_DSPR2 | ASE_EVA | ASE_MIPS3D
-     | ASE_MT | ASE_MCU | ASE_VIRT),
+     | ASE_MT | ASE_MCU | ASE_VIRT | ASE_MSA),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_hwr_names_mips3264r2 },
@@ -513,7 +522,7 @@ const struct mips_arch_choice mips_arch_choices[] =
   { "mips64r2",        1, bfd_mach_mipsisa64r2, CPU_MIPS64R2,
     ISA_MIPS64R2,
     (ASE_MIPS3D | ASE_DSP | ASE_DSPR2 | ASE_DSP64 | ASE_EVA | ASE_MT
-     | ASE_MDMX | ASE_MCU | ASE_VIRT | ASE_VIRT64),
+     | ASE_MCU | ASE_VIRT | ASE_VIRT64 | ASE_MSA | ASE_MSA64),
     mips_cp0_names_mips3264r2,
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_hwr_names_mips3264r2 },
@@ -738,6 +747,14 @@ parse_mips_dis_option (const char *option, unsigned int len)
       return;
     }
 
+  if (CONST_STRNEQ (option, "msa"))
+    {
+      mips_ase |= ASE_MSA;
+      if ((mips_isa & INSN_ISA_MASK) == ISA_MIPS64R2)
+         mips_ase |= ASE_MSA64;
+      return;
+    }
+
   if (CONST_STRNEQ (option, "virt"))
     {
       mips_ase |= ASE_VIRT;
@@ -917,6 +934,39 @@ print_reg (struct disassemble_info *info, const struct mips_opcode *opcode,
     case OP_REG_HW:
       info->fprintf_func (info->stream, "%s", mips_hwr_names[regno]);
       break;
+
+    case OP_REG_VF:
+      info->fprintf_func (info->stream, "$vf%d", regno);
+      break;
+
+    case OP_REG_VI:
+      info->fprintf_func (info->stream, "$vi%d", regno);
+      break;
+
+    case OP_REG_R5900_I:
+      info->fprintf_func (info->stream, "$I");
+      break;
+
+    case OP_REG_R5900_Q:
+      info->fprintf_func (info->stream, "$Q");
+      break;
+
+    case OP_REG_R5900_R:
+      info->fprintf_func (info->stream, "$R");
+      break;
+
+    case OP_REG_R5900_ACC:
+      info->fprintf_func (info->stream, "$ACC");
+      break;
+
+    case OP_REG_MSA:
+      info->fprintf_func (info->stream, "$w%d", regno);
+      break;
+
+    case OP_REG_MSA_CTRL:
+      info->fprintf_func (info->stream, "%s", msa_control_names[regno]);
+      break;
+
     }
 }
 \f
@@ -941,6 +991,25 @@ init_print_arg_state (struct mips_print_arg_state *state)
   memset (state, 0, sizeof (*state));
 }
 
+/* Print OP_VU0_SUFFIX or OP_VU0_MATCH_SUFFIX operand OPERAND,
+   whose value is given by UVAL.  */
+
+static void
+print_vu0_channel (struct disassemble_info *info,
+                  const struct mips_operand *operand, unsigned int uval)
+{
+  if (operand->size == 4)
+    info->fprintf_func (info->stream, "%s%s%s%s",
+                       uval & 8 ? "x" : "",
+                       uval & 4 ? "y" : "",
+                       uval & 2 ? "z" : "",
+                       uval & 1 ? "w" : "");
+  else if (operand->size == 2)
+    info->fprintf_func (info->stream, "%c", "xyzw"[uval]);
+  else
+    abort ();
+}
+
 /* Print operand OPERAND of OPCODE, using STATE to track inter-operand state.
    UVAL is the encoding of the operand (shifted into bit 0) and BASE_PC is
    the base address for OP_PCREL operands.  */
@@ -999,12 +1068,12 @@ print_insn_arg (struct disassemble_info *info,
       break;
 
     case OP_REG:
+    case OP_OPTIONAL_REG:
       {
        const struct mips_reg_operand *reg_op;
 
        reg_op = (const struct mips_reg_operand *) operand;
-       if (reg_op->reg_map)
-         uval = reg_op->reg_map[uval];
+       uval = mips_decode_reg_operand (reg_op, uval);
        print_reg (info, opcode, reg_op->reg_type, uval);
 
        state->last_reg_type = reg_op->reg_type;
@@ -1202,6 +1271,21 @@ print_insn_arg (struct disassemble_info *info,
     case OP_PC:
       infprintf (is, "$pc");
       break;
+
+    case OP_VU0_SUFFIX:
+    case OP_VU0_MATCH_SUFFIX:
+      print_vu0_channel (info, operand, uval);
+      break;
+
+    case OP_IMM_INDEX:
+      infprintf (is, "[%d]", uval);
+      break;
+
+    case OP_REG_INDEX:
+      infprintf (is, "[");
+      print_reg (info, opcode, OP_REG_GP, uval);
+      infprintf (is, "]");
+      break;
     }
 }
 
@@ -1232,6 +1316,11 @@ print_insn_args (struct disassemble_info *info,
          infprintf (is, "%c", *s);
          break;
 
+       case '#':
+         ++s;
+         infprintf (is, "%c%c", *s, *s);
+         break;
+
        default:
          operand = decode_operand (s);
          if (!operand)
@@ -1346,8 +1435,7 @@ print_insn_mips (bfd_vma memaddr,
              /* Figure out instruction type and branch delay information.  */
              if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
                {
-                 if ((op->pinfo & (INSN_WRITE_GPR_31
-                                   | INSN_WRITE_GPR_D)) != 0)
+                 if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
                    info->insn_type = dis_jsr;
                  else
                    info->insn_type = dis_branch;
@@ -1367,6 +1455,14 @@ print_insn_mips (bfd_vma memaddr,
                info->insn_type = dis_dref;
 
              infprintf (is, "%s", op->name);
+             if (op->pinfo2 & INSN2_VU0_CHANNEL_SUFFIX)
+               {
+                 unsigned int uval;
+
+                 infprintf (is, ".");
+                 uval = mips_extract_operand (&mips_vu0_channel_mask, word);
+                 print_vu0_channel (info, &mips_vu0_channel_mask, uval);
+               }
 
              if (op->args[0])
                {
@@ -1565,7 +1661,7 @@ print_mips16_insn_arg (struct disassemble_info *info,
             }
        }
 
-      print_insn_arg (info, state, opcode, operand, baseaddr, uval);
+      print_insn_arg (info, state, opcode, operand, baseaddr + 1, uval);
       break;
     }
 }
@@ -1749,15 +1845,15 @@ print_insn_mips16 (bfd_vma memaddr, struct disassemble_info *info)
          /* Figure out branch instruction type and delay slot information.  */
          if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0)
            info->branch_delay_insns = 1;
-         if ((op->pinfo & (INSN_UNCOND_BRANCH_DELAY
-                           | MIPS16_INSN_UNCOND_BRANCH)) != 0)
+         if ((op->pinfo & INSN_UNCOND_BRANCH_DELAY) != 0
+             || (op->pinfo2 & INSN2_UNCOND_BRANCH) != 0)
            {
              if ((op->pinfo & INSN_WRITE_GPR_31) != 0)
                info->insn_type = dis_jsr;
              else
                info->insn_type = dis_branch;
            }
-         else if ((op->pinfo & MIPS16_INSN_COND_BRANCH) != 0)
+         else if ((op->pinfo2 & INSN2_COND_BRANCH) != 0)
            info->insn_type = dis_condbranch;
 
          return length;
@@ -1894,7 +1990,7 @@ print_insn_micromips (bfd_vma memaddr, struct disassemble_info *info)
          if (((op->pinfo & INSN_UNCOND_BRANCH_DELAY)
               | (op->pinfo2 & INSN2_UNCOND_BRANCH)) != 0)
            {
-             if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_GPR_T)) != 0)
+             if ((op->pinfo & (INSN_WRITE_GPR_31 | INSN_WRITE_1)) != 0)
                info->insn_type = dis_jsr;
              else
                info->insn_type = dis_branch;
@@ -2033,6 +2129,9 @@ print_mips_disassembler_options (FILE *stream)
 The following MIPS specific disassembler options are supported for use\n\
 with the -M switch (multiple options should be separated by commas):\n"));
 
+  fprintf (stream, _("\n\
+  msa             Recognize MSA instructions.\n"));
+
   fprintf (stream, _("\n\
   virt            Recognize the virtualization ASE instructions.\n"));
 
This page took 0.032982 seconds and 4 git commands to generate.