MIPS: Add Imagination interAptiv MR2 MIPS32r3 processor support
authorMaciej W. Rozycki <macro@imgtec.com>
Wed, 28 Jun 2017 01:07:36 +0000 (02:07 +0100)
committerMaciej W. Rozycki <macro@imgtec.com>
Wed, 28 Jun 2017 01:07:36 +0000 (02:07 +0100)
Add support for the Imagination interAptiv MR2 MIPS32r3 processor with
the MIPS16e2 ASE as per documentation, including in particular:

1. Support for implementation-specific interAptiv MR2 COPYW and UCOPYW
   MIPS16e2 instructions[1], for assembly and disassembly,

2. Support for implementation-specific interAptiv MR2 SAVE and RESTORE
   regular MIPS instructions[2], for assembly and disassembly,

3. ELF binary file annotation for the interAptiv MR2 MIPS architecture
   extension.

4. Support for interAptiv MR2 architecture selection for assembly, in
   the form of the `-march=interaptiv-mr2' command-line option and its
   corresponding `arch=interaptiv-mr2' setting for the `.set' and
   `.module' pseudo-ops.

5. Support for interAptiv MR2 architecture selection for disassembly,
   in the form of the `mips:interaptiv-mr2' target architecture, for
   use e.g. with the `-m' command-line option for `objdump'.

Parts of this change by Matthew Fortune and Andrew Bennett.

References:

[1] "MIPS32 interAptiv Multiprocessing System Software User's Manual",
    Imagination Technologies Ltd., Document Number: MD00904, Revision
    02.01, June 15, 2016, Section 24.3 "MIPS16e2 Implementation Specific
    Instructions", pp. 878-883

[2] same, Chapter 25 "Implementation-specific Instructions", pp. 911-917

include/
* elf/mips.h (E_MIPS_MACH_IAMR2): New macro.
(AFL_EXT_INTERAPTIV_MR2): Likewise.
* opcode/mips.h: Document new operand codes defined.
(INSN_INTERAPTIV_MR2): New macro.
(INSN_CHIP_MASK): Adjust accordingly.
(CPU_INTERAPTIV_MR2): New macro.
(cpu_is_member) <CPU_INTERAPTIV_MR2>: New case.
(MIPS16_ALL_ARGS): Rename to...
(MIPS_SVRS_ALL_ARGS): ... this.
(MIPS16_ALL_STATICS): Rename to...
(MIPS_SVRS_ALL_STATICS): ... this.

bfd/
* archures.c (bfd_mach_mips_interaptiv_mr2): New macro.
* cpu-mips.c (I_interaptiv_mr2): New enum value.
(arch_info_struct): Add "mips:interaptiv-mr2" entry.
* elfxx-mips.c (_bfd_elf_mips_mach) <E_MIPS_MACH_IAMR2>: New
case.
(mips_set_isa_flags) <bfd_mach_mips_interaptiv_mr2>: Likewise.
(bfd_mips_isa_ext) <bfd_mach_mips_interaptiv_mr2>: Likewise.
(print_mips_isa_ext) <AFL_EXT_INTERAPTIV_MR2>: Likewise.
(mips_mach_extensions): Add `bfd_mach_mipsisa32r3' and
`bfd_mach_mips_interaptiv_mr2' entries.
* bfd-in2.h: Regenerate.

opcodes/
* mips-formats.h (INT_BIAS): New macro.
(INT_ADJ): Redefine in INT_BIAS terms.
* mips-dis.c (mips_arch_choices): Add "interaptiv-mr2" entry.
(mips_print_save_restore): New function.
(print_insn_arg) <OP_SAVE_RESTORE_LIST>: Update comment.
(validate_insn_args) <OP_SAVE_RESTORE_LIST>: Remove `abort'
call.
(print_insn_args): Handle OP_SAVE_RESTORE_LIST.
(print_mips16_insn_arg): Call `mips_print_save_restore' for
OP_SAVE_RESTORE_LIST handling, factored out from here.
* mips-opc.c (decode_mips_operand) <'-'> <'m'>: New case.
(RD_31, RD_SP, WR_SP, MOD_SP, IAMR2): New macros.
(mips_builtin_opcodes): Add "restore" and "save" entries.
* mips16-opc.c (decode_mips16_operand) <'n', 'o'>: New cases.
(IAMR2): New macro.
(mips16_opcodes): Add "copyw" and "ucopyw" entries.

binutils/
* readelf.c (get_machine_flags) <E_MIPS_MACH_IAMR2>: New case.
(print_mips_isa_ext) <AFL_EXT_INTERAPTIV_MR2>: Likewise.
* NEWS: Mention Imagination interAptiv MR2 processor support.

gas/
* config/tc-mips.c (validate_mips_insn): Handle
OP_SAVE_RESTORE_LIST specially.
(mips_encode_save_restore, mips16_encode_save_restore): New
functions.
(match_save_restore_list_operand): Factor out SAVE/RESTORE
operand insertion into the instruction word or halfword to these
new functions.
(mips_cpu_info_table): Add "interaptiv-mr2" entry.

* doc/c-mips.texi (MIPS Options): Add `interaptiv-mr2' to the
`-march=' argument list.

19 files changed:
bfd/ChangeLog
bfd/archures.c
bfd/bfd-in2.h
bfd/cpu-mips.c
bfd/elfxx-mips.c
binutils/ChangeLog
binutils/NEWS
binutils/readelf.c
gas/ChangeLog
gas/config/tc-mips.c
gas/doc/c-mips.texi
include/ChangeLog
include/elf/mips.h
include/opcode/mips.h
opcodes/ChangeLog
opcodes/mips-dis.c
opcodes/mips-formats.h
opcodes/mips-opc.c
opcodes/mips16-opc.c

index 31fd542..3f81ea4 100644 (file)
@@ -1,3 +1,18 @@
+2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
+           Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * archures.c (bfd_mach_mips_interaptiv_mr2): New macro.
+       * cpu-mips.c (I_interaptiv_mr2): New enum value.
+       (arch_info_struct): Add "mips:interaptiv-mr2" entry.
+       * elfxx-mips.c (_bfd_elf_mips_mach) <E_MIPS_MACH_IAMR2>: New
+       case.
+       (mips_set_isa_flags) <bfd_mach_mips_interaptiv_mr2>: Likewise.
+       (bfd_mips_isa_ext) <bfd_mach_mips_interaptiv_mr2>: Likewise.
+       (print_mips_isa_ext) <AFL_EXT_INTERAPTIV_MR2>: Likewise.
+       (mips_mach_extensions): Add `bfd_mach_mipsisa32r3' and
+       `bfd_mach_mips_interaptiv_mr2' entries.
+       * bfd-in2.h: Regenerate.
+
 2017-06-27  Nick Clifton  <nickc@redhat.com>
 
        * tekhex.c (pass_over): Revert accidental conversion of a local
index 2fefec5..433b95f 100644 (file)
@@ -200,6 +200,7 @@ DESCRIPTION
 .#define bfd_mach_mips_octeon2         6502
 .#define bfd_mach_mips_octeon3          6503
 .#define bfd_mach_mips_xlr              887682   {* decimal 'XLR'  *}
+.#define bfd_mach_mips_interaptiv_mr2   736550   {* decimal 'IA2'  *}
 .#define bfd_mach_mipsisa32             32
 .#define bfd_mach_mipsisa32r2           33
 .#define bfd_mach_mipsisa32r3           34
index 8c312e3..971acb8 100644 (file)
@@ -2059,6 +2059,7 @@ enum bfd_architecture
 #define bfd_mach_mips_octeon2          6502
 #define bfd_mach_mips_octeon3          6503
 #define bfd_mach_mips_xlr              887682   /* decimal 'XLR'  */
+#define bfd_mach_mips_interaptiv_mr2   736550   /* decimal 'IA2'  */
 #define bfd_mach_mipsisa32             32
 #define bfd_mach_mipsisa32r2           33
 #define bfd_mach_mipsisa32r3           34
index 70a8aa7..2493094 100644 (file)
@@ -104,6 +104,7 @@ enum
   I_mipsocteon2,
   I_mipsocteon3,
   I_xlr,
+  I_interaptiv_mr2,
   I_micromips
 };
 
@@ -155,6 +156,8 @@ static const bfd_arch_info_type arch_info_struct[] =
   N (64, 64, bfd_mach_mips_octeon2,"mips:octeon2",  FALSE, NN(I_mipsocteon2)),
   N (64, 64, bfd_mach_mips_octeon3, "mips:octeon3",  FALSE, NN(I_mipsocteon3)),
   N (64, 64, bfd_mach_mips_xlr, "mips:xlr",       FALSE, NN(I_xlr)),
+  N (32, 32, bfd_mach_mips_interaptiv_mr2, "mips:interaptiv-mr2", FALSE,
+     NN(I_interaptiv_mr2)),
   N (64, 64, bfd_mach_mips_micromips,"mips:micromips",FALSE,0)
 };
 
index e326edd..2eb3dd3 100644 (file)
@@ -6793,6 +6793,9 @@ _bfd_elf_mips_mach (flagword flags)
     case E_MIPS_MACH_XLR:
       return bfd_mach_mips_xlr;
 
+    case E_MIPS_MACH_IAMR2:
+      return bfd_mach_mips_interaptiv_mr2;
+
     default:
       switch (flags & EF_MIPS_ARCH)
        {
@@ -11967,6 +11970,10 @@ mips_set_isa_flags (bfd *abfd)
       val = E_MIPS_ARCH_32R2;
       break;
 
+    case bfd_mach_mips_interaptiv_mr2:
+      val = E_MIPS_ARCH_32R2 | E_MIPS_MACH_IAMR2;
+      break;
+
     case bfd_mach_mipsisa64r2:
     case bfd_mach_mipsisa64r3:
     case bfd_mach_mipsisa64r5:
@@ -14026,6 +14033,12 @@ static const struct mips_mach_extension mips_mach_extensions[] =
   { bfd_mach_mips4100, bfd_mach_mips4000 },
   { bfd_mach_mips5900, bfd_mach_mips4000 },
 
+  /* MIPS32r3 extensions.  */
+  { bfd_mach_mips_interaptiv_mr2, bfd_mach_mipsisa32r3 },
+
+  /* MIPS32r2 extensions.  */
+  { bfd_mach_mipsisa32r3, bfd_mach_mipsisa32r2 },
+
   /* MIPS32 extensions.  */
   { bfd_mach_mipsisa32r2, bfd_mach_mipsisa32 },
 
@@ -14123,6 +14136,8 @@ bfd_mips_isa_ext (bfd *abfd)
     case bfd_mach_mips_octeon3:     return AFL_EXT_OCTEON3;
     case bfd_mach_mips_octeon2:     return AFL_EXT_OCTEON2;
     case bfd_mach_mips_xlr:         return AFL_EXT_XLR;
+    case bfd_mach_mips_interaptiv_mr2:
+      return AFL_EXT_INTERAPTIV_MR2;
     default:                        return 0;
     }
 }
@@ -15719,6 +15734,9 @@ print_mips_isa_ext (FILE *file, unsigned int isa_ext)
     case AFL_EXT_LOONGSON_2F:
       fputs ("ST Microelectronics Loongson 2F", file);
       break;
+    case AFL_EXT_INTERAPTIV_MR2:
+      fputs ("Imagination interAptiv MR2", file);
+      break;
     default:
       fprintf (file, "%s (%d)", _("Unknown"), isa_ext);
       break;
index af2a348..da3cf67 100644 (file)
@@ -1,3 +1,10 @@
+2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
+           Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * readelf.c (get_machine_flags) <E_MIPS_MACH_IAMR2>: New case.
+       (print_mips_isa_ext) <AFL_EXT_INTERAPTIV_MR2>: Likewise.
+       * NEWS: Mention Imagination interAptiv MR2 processor support.
+
 2017-06-26  Nick Clifton  <nickc@redhat.com>
 
        PR binutils/21665
index 753d17f..b49e2d3 100644 (file)
@@ -1,5 +1,9 @@
 -*- text -*-
 
+* The MIPS port now supports the Imagination interAptiv MR2 processor,
+  which implements the MIPS32r3 ISA, the MIPS16e2 ASE as well as a couple
+  of implementation-specific regular MIPS and MIPS16e2 ASE instructions.
+
 * The SPARC port now supports the SPARC M8 processor, which implements the
   Oracle SPARC Architecture 2017.
 
index 916c6cb..edfe652 100644 (file)
@@ -3334,6 +3334,7 @@ get_machine_flags (unsigned e_flags, unsigned e_machine)
            case E_MIPS_MACH_OCTEON2: strcat (buf, ", octeon2"); break;
            case E_MIPS_MACH_OCTEON3: strcat (buf, ", octeon3"); break;
            case E_MIPS_MACH_XLR:  strcat (buf, ", xlr"); break;
+           case E_MIPS_MACH_IAMR2:  strcat (buf, ", interaptiv-mr2"); break;
            case 0:
            /* We simply ignore the field in this case to avoid confusion:
               MIPS ELF does not specify EF_MIPS_MACH, it is a GNU
@@ -15131,6 +15132,9 @@ print_mips_isa_ext (unsigned int isa_ext)
     case AFL_EXT_LOONGSON_2F:
       fputs ("ST Microelectronics Loongson 2F", stdout);
       break;
+    case AFL_EXT_INTERAPTIV_MR2:
+      fputs ("Imagination interAptiv MR2", stdout);
+      break;
     default:
       fprintf (stdout, "%s (%d)", _("Unknown"), isa_ext);
     }
index 6a3437b..69e6547 100644 (file)
@@ -1,3 +1,18 @@
+2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
+           Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * config/tc-mips.c (validate_mips_insn): Handle
+       OP_SAVE_RESTORE_LIST specially.
+       (mips_encode_save_restore, mips16_encode_save_restore): New
+       functions.
+       (match_save_restore_list_operand): Factor out SAVE/RESTORE
+       operand insertion into the instruction word or halfword to these
+       new functions.
+       (mips_cpu_info_table): Add "interaptiv-mr2" entry.
+
+       * doc/c-mips.texi (MIPS Options): Add `interaptiv-mr2' to the
+       `-march=' argument list.
+
 2017-06-27  Maciej W. Rozycki  <macro@imgtec.com>
 
        * testsuite/gas/mips/mips16e-save.d: Rename to...
index ecd3c8e..d7a1ff3 100644 (file)
@@ -3463,6 +3463,10 @@ validate_mips_insn (const struct mips_opcode *opcode,
              used_bits &= ~(1 << (operand->lsb + 5));
            if (operand->type == OP_ENTRY_EXIT_LIST)
              used_bits &= ~(mask & 0x700);
+           /* interAptiv MR2 SAVE/RESTORE instructions have a discontiguous
+              operand field that cannot be fully described with LSB/SIZE.  */
+           if (operand->type == OP_SAVE_RESTORE_LIST && operand->lsb == 6)
+             used_bits &= ~0x6000;
          }
        /* Skip prefix characters.  */
        if (decode_operand && (*s == '+' || *s == 'm' || *s == '-'))
@@ -5555,6 +5559,39 @@ match_entry_exit_operand (struct mips_arg_info *arg,
   return TRUE;
 }
 
+/* Encode regular MIPS SAVE/RESTORE instruction operands according to
+   the argument register mask AMASK, the number of static registers
+   saved NSREG, the $ra, $s0 and $s1 register specifiers RA, S0 and S1
+   respectively, and the frame size FRAME_SIZE.  */
+
+static unsigned int
+mips_encode_save_restore (unsigned int amask, unsigned int nsreg,
+                         unsigned int ra, unsigned int s0, unsigned int s1,
+                         unsigned int frame_size)
+{
+  return ((nsreg << 23) | ((frame_size & 0xf0) << 15) | (amask << 15)
+         | (ra << 12) | (s0 << 11) | (s1 << 10) | ((frame_size & 0xf) << 6));
+}
+
+/* Encode MIPS16 SAVE/RESTORE instruction operands according to the
+   argument register mask AMASK, the number of static registers saved
+   NSREG, the $ra, $s0 and $s1 register specifiers RA, S0 and S1
+   respectively, and the frame size FRAME_SIZE.  */
+
+static unsigned int
+mips16_encode_save_restore (unsigned int amask, unsigned int nsreg,
+                           unsigned int ra, unsigned int s0, unsigned int s1,
+                           unsigned int frame_size)
+{
+  unsigned int args;
+
+  args = (ra << 6) | (s0 << 5) | (s1 << 4) | (frame_size & 0xf);
+  if (nsreg || amask || frame_size == 0 || frame_size > 16)
+    args |= (MIPS16_EXTEND | (nsreg << 24) | (amask << 16)
+            | ((frame_size & 0xf0) << 16));
+  return args;
+}
+
 /* OP_SAVE_RESTORE_LIST matcher.  */
 
 static bfd_boolean
@@ -5562,6 +5599,7 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
 {
   unsigned int opcode, args, statics, sregs;
   unsigned int num_frame_sizes, num_args, num_statics, num_sregs;
+  unsigned int arg_mask, ra, s0, s1;
   offsetT frame_size;
 
   opcode = arg->insn->insn_opcode;
@@ -5570,6 +5608,9 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
   args = 0;
   statics = 0;
   sregs = 0;
+  ra = 0;
+  s0 = 0;
+  s1 = 0;
   do
     {
       unsigned int regno1, regno2;
@@ -5605,7 +5646,7 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
                sregs |= 1 << 8;
              else if (regno1 == 31)
                /* Add $ra to insn.  */
-               opcode |= 0x40;
+               ra = 1;
              else
                return FALSE;
              regno1 += 1;
@@ -5621,10 +5662,10 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
     return FALSE;
   else if (args == 0xf)
     /* All $a0-$a3 are args.  */
-    opcode |= MIPS16_ALL_ARGS << 16;
+    arg_mask = MIPS_SVRS_ALL_ARGS;
   else if (statics == 0xf)
     /* All $a0-$a3 are statics.  */
-    opcode |= MIPS16_ALL_STATICS << 16;
+    arg_mask = MIPS_SVRS_ALL_STATICS;
   else
     {
       /* Count arg registers.  */
@@ -5648,14 +5689,14 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
        return FALSE;
 
       /* Encode args/statics.  */
-      opcode |= ((num_args << 2) | num_statics) << 16;
+      arg_mask = (num_args << 2) | num_statics;
     }
 
   /* Encode $s0/$s1.  */
   if (sregs & (1 << 0))                /* $s0 */
-    opcode |= 0x20;
+    s0 = 1;
   if (sregs & (1 << 1))                /* $s1 */
-    opcode |= 0x10;
+    s1 = 1;
   sregs >>= 2;
 
   /* Encode $s2-$s8. */
@@ -5667,7 +5708,6 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
     }
   if (sregs != 0)
     return FALSE;
-  opcode |= num_sregs << 24;
 
   /* Encode frame size.  */
   if (num_frame_sizes == 0)
@@ -5685,16 +5725,18 @@ match_save_restore_list_operand (struct mips_arg_info *arg)
       set_insn_error (arg->argnum, _("invalid frame size"));
       return FALSE;
     }
-  if (frame_size != 128 || (opcode >> 16) != 0)
-    {
-      frame_size /= 8;
-      opcode |= (((frame_size & 0xf0) << 16)
-                | (frame_size & 0x0f));
-    }
+  frame_size /= 8;
 
   /* Finally build the instruction.  */
-  if ((opcode >> 16) != 0 || frame_size == 0)
-    opcode |= MIPS16_EXTEND;
+  if (mips_opts.mips16)
+    opcode |= mips16_encode_save_restore (arg_mask, num_sregs, ra, s0, s1,
+                                         frame_size);
+  else if (!mips_opts.micromips)
+    opcode |= mips_encode_save_restore (arg_mask, num_sregs, ra, s0, s1,
+                                       frame_size);
+  else
+    abort ();
+
   arg->insn->insn_opcode = opcode;
   return TRUE;
 }
@@ -19665,6 +19707,9 @@ static const struct mips_cpu_info mips_cpu_info_table[] =
   { "1004kf1_1",      0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
   /* interaptiv is the new name for 1004kf */
   { "interaptiv",     0, ASE_DSP | ASE_MT,     ISA_MIPS32R2, CPU_MIPS32R2 },
+  { "interaptiv-mr2", 0,
+    ASE_DSP | ASE_EVA | ASE_MT | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
+    ISA_MIPS32R3, CPU_INTERAPTIV_MR2 },
   /* M5100 family */
   { "m5100",          0, ASE_MCU,              ISA_MIPS32R5, CPU_MIPS32R5 },
   { "m5101",          0, ASE_MCU,              ISA_MIPS32R5, CPU_MIPS32R5 },
index c2d9b7a..a430b0d 100644 (file)
@@ -383,6 +383,7 @@ m14kec,
 1004kf,
 1004kf1_1,
 interaptiv,
+interaptiv-mr2,
 m5100,
 m5101,
 p5600,
index 243c730..dd2aab5 100644 (file)
@@ -1,3 +1,18 @@
+2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
+           Matthew Fortune  <matthew.fortune@imgtec.com>
+
+       * elf/mips.h (E_MIPS_MACH_IAMR2): New macro.
+       (AFL_EXT_INTERAPTIV_MR2): Likewise.
+       * opcode/mips.h: Document new operand codes defined.
+       (INSN_INTERAPTIV_MR2): New macro.
+       (INSN_CHIP_MASK): Adjust accordingly.
+       (CPU_INTERAPTIV_MR2): New macro.
+       (cpu_is_member) <CPU_INTERAPTIV_MR2>: New case.
+       (MIPS16_ALL_ARGS): Rename to...
+       (MIPS_SVRS_ALL_ARGS): ... this.
+       (MIPS16_ALL_STATICS): Rename to...
+       (MIPS_SVRS_ALL_STATICS): ... this.
+
 2017-06-26  Kuan-Lin Chen  <rufus@andestech.com>
 
        * elf/riscv.h (R_RISCV_32_PCREL): New.
index b878636..a4bea43 100644 (file)
@@ -294,6 +294,7 @@ END_RELOC_NUMBERS (R_MIPS_maxext)
 #define E_MIPS_MACH_OCTEON3    0x008e0000
 #define E_MIPS_MACH_5400       0x00910000
 #define E_MIPS_MACH_5900       0x00920000
+#define E_MIPS_MACH_IAMR2      0x00930000
 #define E_MIPS_MACH_5500       0x00980000
 #define E_MIPS_MACH_9000       0x00990000
 #define E_MIPS_MACH_LS2E        0x00A00000
@@ -1257,6 +1258,7 @@ extern void bfd_mips_elf_swap_abiflags_v0_out
 #define AFL_EXT_LOONGSON_2E  17  /* ST Microelectronics Loongson 2E.  */
 #define AFL_EXT_LOONGSON_2F  18  /* ST Microelectronics Loongson 2F.  */
 #define AFL_EXT_OCTEON3      19  /* Cavium Networks Octeon3.  */
+#define AFL_EXT_INTERAPTIV_MR2 20  /* Imagination interAptiv MR2.  */
 
 /* Masks for the flags1 word of an ABI flags structure.  */
 #define AFL_FLAGS1_ODDSPREG   1         /* Uses odd single-precision registers.  */
index c71a33a..1b3b2c6 100644 (file)
@@ -935,6 +935,9 @@ mips_opcode_32bit_p (const struct mips_opcode *mo)
    "+z" 5-bit rz register (OP_*_RZ)
    "+Z" 5-bit fz register (OP_*_FZ)
 
+   interAptiv MR2:
+   "-m" register list for SAVE/RESTORE instruction
+
    Enhanced VA Scheme:
    "+j" 9-bit signed offset in bit 7 (OP_*_EVAOFFSET)
 
@@ -1007,7 +1010,7 @@ mips_opcode_32bit_p (const struct mips_opcode *mo)
    Extension character sequences used so far ("-" followed by the
    following), for quick reference when adding more:
    "AB"
-   "abdstuvwxy"
+   "abdmstuvwxy"
 */
 
 /* These are the bits which may be set in the pinfo field of an
@@ -1214,7 +1217,7 @@ static const unsigned int mips_isa_table[] = {
 #undef ISAF
 
 /* Masks used for Chip specific instructions.  */
-#define INSN_CHIP_MASK           0xc3ff4f60
+#define INSN_CHIP_MASK           0xc7ff4f60
 
 /* Cavium Networks Octeon instructions.  */
 #define INSN_OCTEON              0x00000800
@@ -1254,6 +1257,8 @@ static const unsigned int mips_isa_table[] = {
 #define INSN_LOONGSON_3A          0x00000400
 /* RMI Xlr instruction */
 #define INSN_XLR                 0x00000020
+/* Imagination interAptiv MR2.  */
+#define INSN_INTERAPTIV_MR2      0x04000000
 
 /* DSP ASE */
 #define ASE_DSP                        0x00000001
@@ -1356,6 +1361,7 @@ static const unsigned int mips_isa_table[] = {
 #define CPU_OCTEON2    6502
 #define CPU_OCTEON3    6503
 #define CPU_XLR        887682          /* decimal 'XLR'   */
+#define CPU_INTERAPTIV_MR2 736550      /* decimal 'IA2'  */
 
 /* Return true if the given CPU is included in INSN_* mask MASK.  */
 
@@ -1426,6 +1432,9 @@ cpu_is_member (int cpu, unsigned int mask)
     case CPU_XLR:
       return (mask & INSN_XLR) != 0;
 
+    case CPU_INTERAPTIV_MR2:
+      return (mask & INSN_INTERAPTIV_MR2) != 0;
+
     case CPU_MIPS32R6:
       return (mask & INSN_ISA_MASK) == INSN_ISA32R6;
 
@@ -1847,6 +1856,8 @@ extern int bfd_mips_num_opcodes;
    "d" 5-bit EXT size, which becomes MSBD
        Requires that "b" occurs first to set position.
        Enforces: 0 < (pos+size) <= 32.
+   "n" 2-bit immediate (1 .. 4)
+   "o" 5-bit unsigned immediate * 16
    "r" 3-bit register
    "s" 3-bit ASMACRO select immediate
    "u" 16-bit unsigned immediate
@@ -1882,13 +1893,13 @@ extern int bfd_mips_num_opcodes;
    "0123456 89"
    ".[]<>"
    "ABCDEFGHI KLMNOPQRSTUVWXYZ"
-   "abcde   ijklm  pqrs uvwxyz"
+   "abcde   ijklmnopqrs uvwxyz"
   */
 
 /* Save/restore encoding for the args field when all 4 registers are
    either saved as arguments or saved/restored as statics.  */
-#define MIPS16_ALL_ARGS    0xe
-#define MIPS16_ALL_STATICS 0xb
+#define MIPS_SVRS_ALL_ARGS    0xe
+#define MIPS_SVRS_ALL_STATICS 0xb
 
 /* The following flags have the same value for the mips16 opcode
    table:
index 5371bbb..64bc5fa 100644 (file)
@@ -1,3 +1,24 @@
+2017-06-28  Maciej W. Rozycki  <macro@imgtec.com>
+           Matthew Fortune  <matthew.fortune@imgtec.com>
+           Andrew Bennett <andrew.bennett@imgtec.com>
+
+       * mips-formats.h (INT_BIAS): New macro.
+       (INT_ADJ): Redefine in INT_BIAS terms.
+       * mips-dis.c (mips_arch_choices): Add "interaptiv-mr2" entry.
+       (mips_print_save_restore): New function.
+       (print_insn_arg) <OP_SAVE_RESTORE_LIST>: Update comment.
+       (validate_insn_args) <OP_SAVE_RESTORE_LIST>: Remove `abort'
+       call.
+       (print_insn_args): Handle OP_SAVE_RESTORE_LIST.
+       (print_mips16_insn_arg): Call `mips_print_save_restore' for
+       OP_SAVE_RESTORE_LIST handling, factored out from here.
+       * mips-opc.c (decode_mips_operand) <'-'> <'m'>: New case.
+       (RD_31, RD_SP, WR_SP, MOD_SP, IAMR2): New macros.
+       (mips_builtin_opcodes): Add "restore" and "save" entries.
+       * mips16-opc.c (decode_mips16_operand) <'n', 'o'>: New cases.
+       (IAMR2): New macro.
+       (mips16_opcodes): Add "copyw" and "ucopyw" entries.
+
 2017-06-23  Andrew Waterman  <andrew@sifive.com>
 
        * riscv-opc.c (riscv_opcodes): Mark I-type SLT instruction as an
index b541e03..e19d59a 100644 (file)
@@ -607,6 +607,13 @@ const struct mips_arch_choice mips_arch_choices[] =
     mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
     mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
 
+  { "interaptiv-mr2",  1, bfd_mach_mips_interaptiv_mr2, CPU_INTERAPTIV_MR2,
+    ISA_MIPS32R3,
+    ASE_MT | ASE_EVA | ASE_DSP | ASE_DSPR2 | ASE_MIPS16E2 | ASE_MIPS16E2_MT,
+    mips_cp0_names_mips3264r2,
+    mips_cp0sel_names_mips3264r2, ARRAY_SIZE (mips_cp0sel_names_mips3264r2),
+    mips_cp1_names_mips3264, mips_hwr_names_mips3264r2 },
+
   { "sb1",     1, bfd_mach_mips_sb1, CPU_SB1,
     ISA_MIPS64 | INSN_SB1,  ASE_MIPS3D,
     mips_cp0_names_sb1,
@@ -1197,6 +1204,81 @@ mips_seen_register (struct mips_print_arg_state *state,
     }
 }
 
+/* Print SAVE/RESTORE instruction operands according to the argument
+   register mask AMASK, the number of static registers saved NSREG,
+   the $ra, $s0 and $s1 register specifiers RA, S0 and S1 respectively,
+   and the frame size FRAME_SIZE.  */
+
+static void
+mips_print_save_restore (struct disassemble_info *info, unsigned int amask,
+                        unsigned int nsreg, unsigned int ra,
+                        unsigned int s0, unsigned int s1,
+                        unsigned int frame_size)
+{
+  const fprintf_ftype infprintf = info->fprintf_func;
+  unsigned int nargs, nstatics, smask, i, j;
+  void *is = info->stream;
+  const char *sep;
+
+  if (amask == MIPS_SVRS_ALL_ARGS)
+    {
+      nargs = 4;
+      nstatics = 0;
+    }
+  else if (amask == MIPS_SVRS_ALL_STATICS)
+    {
+      nargs = 0;
+      nstatics = 4;
+    }
+  else
+    {
+      nargs = amask >> 2;
+      nstatics = amask & 3;
+    }
+
+  sep = "";
+  if (nargs > 0)
+    {
+      infprintf (is, "%s", mips_gpr_names[4]);
+      if (nargs > 1)
+       infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
+      sep = ",";
+    }
+
+  infprintf (is, "%s%d", sep, frame_size);
+
+  if (ra)                      /* $ra */
+    infprintf (is, ",%s", mips_gpr_names[31]);
+
+  smask = 0;
+  if (s0)                      /* $s0 */
+    smask |= 1 << 0;
+  if (s1)                      /* $s1 */
+    smask |= 1 << 1;
+  if (nsreg > 0)               /* $s2-$s8 */
+    smask |= ((1 << nsreg) - 1) << 2;
+
+  for (i = 0; i < 9; i++)
+    if (smask & (1 << i))
+      {
+       infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
+       /* Skip over string of set bits.  */
+       for (j = i; smask & (2 << j); j++)
+         continue;
+       if (j > i)
+         infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
+       i = j + 1;
+      }
+  /* Statics $ax - $a3.  */
+  if (nstatics == 1)
+    infprintf (is, ",%s", mips_gpr_names[7]);
+  else if (nstatics > 0)
+    infprintf (is, ",%s-%s",
+              mips_gpr_names[7 - nstatics + 1],
+              mips_gpr_names[7]);
+}
+
+
 /* 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.  */
@@ -1429,7 +1511,7 @@ print_insn_arg (struct disassemble_info *info,
       break;
 
     case OP_SAVE_RESTORE_LIST:
-      /* Should be handled by the caller due to extend behavior.  */
+      /* Should be handled by the caller due to complex behavior.  */
       abort ();
 
     case OP_MDMX_IMM_REG:
@@ -1590,11 +1672,8 @@ validate_insn_args (const struct mips_opcode *opcode,
                case OP_VU0_MATCH_SUFFIX:
                case OP_IMM_INDEX:
                case OP_REG_INDEX:
-                 break;
-
                case OP_SAVE_RESTORE_LIST:
-               /* Should be handled by the caller due to extend behavior.  */
-                 abort ();
+                 break;
                }
            }
          if (*s == 'm' || *s == '+' || *s == '-')
@@ -1647,10 +1726,24 @@ print_insn_args (struct disassemble_info *info,
                         opcode->name, opcode->args);
              return;
            }
-         if (operand->type == OP_REG
-             && s[1] == ','
-             && s[2] == 'H'
-             && opcode->name[strlen (opcode->name) - 1] == '0')
+
+         if (operand->type == OP_SAVE_RESTORE_LIST)
+           {
+             /* Handle this case here because of the complex behavior.  */
+             unsigned int amask = (insn >> 15) & 0xf;
+             unsigned int nsreg = (insn >> 23) & 0x7;
+             unsigned int ra = insn & 0x1000;                  /* $ra */
+             unsigned int s0 = insn & 0x800;                   /* $s0 */
+             unsigned int s1 = insn & 0x400;                   /* $s1 */
+             unsigned int frame_size = (((insn >> 15) & 0xf0)
+                                        | ((insn >> 6) & 0x0f)) * 8;
+             mips_print_save_restore (info, amask, nsreg, ra, s0, s1,
+                                      frame_size);
+           }
+         else if (operand->type == OP_REG
+                  && s[1] == ','
+                  && s[2] == 'H'
+                  && opcode->name[strlen (opcode->name) - 1] == '0')
            {
              /* Coprocessor register 0 with sel field.  */
              const struct mips_cp0sel_name *n;
@@ -1864,70 +1957,15 @@ print_mips16_insn_arg (struct disassemble_info *info,
        {
          /* Handle this case here because of the complex interaction
             with the EXTEND opcode.  */
-         unsigned int amask, nargs, nstatics, nsreg, smask, frame_size, i, j;
-         const char *sep;
-
-         amask = extend & 0xf;
-         if (amask == MIPS16_ALL_ARGS)
-           {
-             nargs = 4;
-             nstatics = 0;
-           }
-         else if (amask == MIPS16_ALL_STATICS)
-           {
-             nargs = 0;
-             nstatics = 4;
-           }
-         else
-           {
-             nargs = amask >> 2;
-             nstatics = amask & 3;
-           }
-
-         sep = "";
-         if (nargs > 0)
-           {
-             infprintf (is, "%s", mips_gpr_names[4]);
-             if (nargs > 1)
-               infprintf (is, "-%s", mips_gpr_names[4 + nargs - 1]);
-             sep = ",";
-           }
-
-         frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
+         unsigned int amask = extend & 0xf;
+         unsigned int nsreg = (extend >> 8) & 0x7;
+         unsigned int ra = insn & 0x40;                        /* $ra */
+         unsigned int s0 = insn & 0x20;                        /* $s0 */
+         unsigned int s1 = insn & 0x10;                        /* $s1 */
+         unsigned int frame_size = ((extend & 0xf0) | (insn & 0x0f)) * 8;
          if (frame_size == 0 && !use_extend)
            frame_size = 128;
-         infprintf (is, "%s%d", sep, frame_size);
-
-         if (insn & 0x40)              /* $ra */
-           infprintf (is, ",%s", mips_gpr_names[31]);
-
-         nsreg = (extend >> 8) & 0x7;
-         smask = 0;
-         if (insn & 0x20)              /* $s0 */
-           smask |= 1 << 0;
-         if (insn & 0x10)              /* $s1 */
-           smask |= 1 << 1;
-         if (nsreg > 0)                /* $s2-$s8 */
-           smask |= ((1 << nsreg) - 1) << 2;
-
-         for (i = 0; i < 9; i++)
-           if (smask & (1 << i))
-             {
-               infprintf (is, ",%s", mips_gpr_names[i == 8 ? 30 : (16 + i)]);
-               /* Skip over string of set bits.  */
-               for (j = i; smask & (2 << j); j++)
-                 continue;
-               if (j > i)
-                 infprintf (is, "-%s", mips_gpr_names[j == 8 ? 30 : (16 + j)]);
-               i = j + 1;
-             }
-         /* Statics $ax - $a3.  */
-         if (nstatics == 1)
-           infprintf (is, ",%s", mips_gpr_names[7]);
-         else if (nstatics > 0)
-           infprintf (is, ",%s-%s",
-                      mips_gpr_names[7 - nstatics + 1],
-                      mips_gpr_names[7]);
+         mips_print_save_restore (info, amask, nsreg, ra, s0, s1, frame_size);
          break;
        }
 
index 5277a83..7c8ea4e 100644 (file)
 /* For ARRAY_SIZE.  */
 #include "libiberty.h"
 
-#define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \
+#define INT_BIAS(SIZE, LSB, MAX_VAL, BIAS, SHIFT, PRINT_HEX) \
   { \
     static const struct mips_int_operand op = { \
-      { OP_INT, SIZE, LSB }, MAX_VAL, 0, SHIFT, PRINT_HEX \
+      { OP_INT, SIZE, LSB }, MAX_VAL, BIAS, SHIFT, PRINT_HEX \
     }; \
     return &op.root; \
   }
 
+#define INT_ADJ(SIZE, LSB, MAX_VAL, SHIFT, PRINT_HEX) \
+  INT_BIAS(SIZE, LSB, MAX_VAL, 0, SHIFT, PRINT_HEX)
+
 #define UINT(SIZE, LSB) \
   INT_ADJ(SIZE, LSB, (1 << (SIZE)) - 1, 0, FALSE)
 
index e47d1fd..b151bae 100644 (file)
@@ -46,6 +46,7 @@ decode_mips_operand (const char *p)
        case 'a': INT_ADJ (19, 0, 262143, 2, FALSE);
        case 'b': INT_ADJ (18, 0, 131071, 3, FALSE);
        case 'd': SPECIAL (0, 0, REPEAT_DEST_REG);
+       case 'm': SPECIAL (20, 6, SAVE_RESTORE_LIST);
        case 's': SPECIAL (5, 21, NON_ZERO_REG);
        case 't': SPECIAL (5, 16, NON_ZERO_REG);
        case 'u': PREV_CHECK (5, 16, TRUE, FALSE, FALSE, FALSE);
@@ -232,6 +233,7 @@ decode_mips_operand (const char *p)
 #define RD_2   INSN_READ_2
 #define RD_3   INSN_READ_3
 #define RD_4   INSN_READ_4
+#define RD_31  INSN2_READ_GPR_31
 #define MOD_1  (WR_1|RD_1)
 #define MOD_2  (WR_2|RD_2)
 
@@ -261,6 +263,10 @@ decode_mips_operand (const char *p)
 #define RD_HILO RD_HI|RD_LO
 #define MOD_HILO WR_HILO|RD_HILO
 
+#define RD_SP  INSN2_READ_SP
+#define WR_SP  INSN2_WRITE_SP
+#define MOD_SP (RD_SP|WR_SP)
+
 #define IS_M    INSN_MULT
 
 #define WR_MACC INSN2_WRITE_MDMX_ACC
@@ -321,6 +327,7 @@ decode_mips_operand (const char *p)
 #define IOCT2  (INSN_OCTEON2 | INSN_OCTEON3)
 #define IOCT3  INSN_OCTEON3
 #define XLR     INSN_XLR
+#define IAMR2  INSN_INTERAPTIV_MR2
 #define IVIRT  ASE_VIRT
 #define IVIRT64        ASE_VIRT64
 
@@ -3151,6 +3158,10 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"cfcmsa",             "+k,+n",        0x787e0019, 0xffff003f, WR_1|CM,                0,              0,              MSA,    0 },
 {"move.v",             "+d,+e",        0x78be0019, 0xffff003f, WR_1|RD_2,              0,              0,              MSA,    0 },
 
+/* interAptiv MR2 instruction extensions.  */
+{"restore",            "-m",           0x7000001f, 0xfc00603f, WR_31|NODS,             MOD_SP,         IAMR2,          0,      0 },
+{"save",               "-m",           0x7000201f, 0xfc00603f, NODS,                   RD_31|MOD_SP,   IAMR2,          0,      0 },
+
 /* User Defined Instruction.  */
 {"udi0",               "s,t,d,+1",     0x70000010, 0xfc00003f, UDI,                    0,              I33,            0,      0 },
 {"udi0",               "s,t,+2",       0x70000010, 0xfc00003f, UDI,                    0,              I33,            0,      0 },
index 83663ad..0ee71be 100644 (file)
@@ -82,6 +82,8 @@ decode_mips16_operand (char type, bfd_boolean extended_p)
     case 'i': JALX (26, 0, 2);
     case 'l': SPECIAL (6, 5, ENTRY_EXIT_LIST);
     case 'm': SPECIAL (7, 0, SAVE_RESTORE_LIST);
+    case 'n': INT_BIAS (2, 0, 3, 1, 0, FALSE); /* (1 .. 4) */
+    case 'o': INT_ADJ (5, 16, 31, 4, FALSE);   /* (0 .. 31) << 4 */
     case 'r': MAPPED_REG (3, 16, GP, reg_m16_map);
     case 's': HINT (3, 24);
     case 'u': HINT (16, 0);
@@ -201,6 +203,7 @@ decode_mips16_operand (char type, bfd_boolean extended_p)
 #define I32    INSN_ISA32
 #define I64    INSN_ISA64
 #define T3     INSN_3900
+#define IAMR2  INSN_INTERAPTIV_MR2
 
 #define E2     ASE_MIPS16E2
 #define E2MT   ASE_MIPS16E2_MT
@@ -465,6 +468,9 @@ const struct mips_opcode mips16_opcodes[] =
 {"evpe",    "",                0xf0276700, 0xffffffff, WR_C0,                  0,              0,      E2MT,   0 },
 {"evpe",    ".",       0xf0276700, 0xffffffff, WR_C0,                  0,              0,      E2MT,   0 },
 {"evpe",    "y",       0xf0236700, 0xffffff1f, WR_1|WR_C0,             0,              0,      E2MT,   0 },
+  /* interAptiv MR2 instruction extensions.  */
+{"copyw",   "x,y,o,n", 0xf020e000, 0xffe0f81c, RD_1|RD_2|NODS,         0,              IAMR2,  0,      0 },
+{"ucopyw",  "x,y,o,n", 0xf000e000, 0xffe0f81c, RD_1|RD_2|NODS,         0,              IAMR2,  0,      0 },
   /* Place asmacro at the bottom so that it catches any implementation
      specific macros that didn't match anything.  */
 {"asmacro", "s,0,1,2,3,4", 0xf000e000, 0xf800f800, 0,                  0,              I32,    0,      0 },