From: Maciej W. Rozycki Date: Wed, 28 Jun 2017 01:07:36 +0000 (+0100) Subject: MIPS: Add Imagination interAptiv MR2 MIPS32r3 processor support X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=38bf472a15210c222bb3885820e763c47760a704;p=binutils-gdb.git MIPS: Add Imagination interAptiv MR2 MIPS32r3 processor support 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) : 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) : New case. (mips_set_isa_flags) : Likewise. (bfd_mips_isa_ext) : Likewise. (print_mips_isa_ext) : 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) : Update comment. (validate_insn_args) : 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) : New case. (print_mips_isa_ext) : 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 31fd5428663..3f81ea45d08 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,18 @@ +2017-06-28 Maciej W. Rozycki + Matthew Fortune + + * 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) : New + case. + (mips_set_isa_flags) : Likewise. + (bfd_mips_isa_ext) : Likewise. + (print_mips_isa_ext) : Likewise. + (mips_mach_extensions): Add `bfd_mach_mipsisa32r3' and + `bfd_mach_mips_interaptiv_mr2' entries. + * bfd-in2.h: Regenerate. + 2017-06-27 Nick Clifton * tekhex.c (pass_over): Revert accidental conversion of a local diff --git a/bfd/archures.c b/bfd/archures.c index 2fefec55a6e..433b95fa088 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -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 diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8c312e3f9ef..971acb8e188 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -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 diff --git a/bfd/cpu-mips.c b/bfd/cpu-mips.c index 70a8aa71cc6..2493094bef2 100644 --- a/bfd/cpu-mips.c +++ b/bfd/cpu-mips.c @@ -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) }; diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index e326edd3257..2eb3dd3363c 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -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; diff --git a/binutils/ChangeLog b/binutils/ChangeLog index af2a348d5b7..da3cf67a95a 100644 --- a/binutils/ChangeLog +++ b/binutils/ChangeLog @@ -1,3 +1,10 @@ +2017-06-28 Maciej W. Rozycki + Matthew Fortune + + * readelf.c (get_machine_flags) : New case. + (print_mips_isa_ext) : Likewise. + * NEWS: Mention Imagination interAptiv MR2 processor support. + 2017-06-26 Nick Clifton PR binutils/21665 diff --git a/binutils/NEWS b/binutils/NEWS index 753d17f3056..b49e2d31ea9 100644 --- a/binutils/NEWS +++ b/binutils/NEWS @@ -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. diff --git a/binutils/readelf.c b/binutils/readelf.c index 916c6cb986c..edfe652a7a4 100644 --- a/binutils/readelf.c +++ b/binutils/readelf.c @@ -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); } diff --git a/gas/ChangeLog b/gas/ChangeLog index 6a3437b6a1a..69e65476a02 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,18 @@ +2017-06-28 Maciej W. Rozycki + Matthew Fortune + + * 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 * testsuite/gas/mips/mips16e-save.d: Rename to... diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c index ecd3c8e6310..d7a1ff3ca9b 100644 --- a/gas/config/tc-mips.c +++ b/gas/config/tc-mips.c @@ -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 }, diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi index c2d9b7ae5b5..a430b0dfd78 100644 --- a/gas/doc/c-mips.texi +++ b/gas/doc/c-mips.texi @@ -383,6 +383,7 @@ m14kec, 1004kf, 1004kf1_1, interaptiv, +interaptiv-mr2, m5100, m5101, p5600, diff --git a/include/ChangeLog b/include/ChangeLog index 243c7303cd6..dd2aab537fd 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,18 @@ +2017-06-28 Maciej W. Rozycki + Matthew Fortune + + * 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) : 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 * elf/riscv.h (R_RISCV_32_PCREL): New. diff --git a/include/elf/mips.h b/include/elf/mips.h index b8786364f12..a4bea43ff83 100644 --- a/include/elf/mips.h +++ b/include/elf/mips.h @@ -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. */ diff --git a/include/opcode/mips.h b/include/opcode/mips.h index c71a33a1a35..1b3b2c62f67 100644 --- a/include/opcode/mips.h +++ b/include/opcode/mips.h @@ -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: diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 5371bbb57b3..64bc5fa613b 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,24 @@ +2017-06-28 Maciej W. Rozycki + Matthew Fortune + Andrew Bennett + + * 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) : Update comment. + (validate_insn_args) : 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 * riscv-opc.c (riscv_opcodes): Mark I-type SLT instruction as an diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index b541e03b852..e19d59a703d 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -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; } diff --git a/opcodes/mips-formats.h b/opcodes/mips-formats.h index 5277a832920..7c8ea4e42aa 100644 --- a/opcodes/mips-formats.h +++ b/opcodes/mips-formats.h @@ -18,14 +18,17 @@ /* 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) diff --git a/opcodes/mips-opc.c b/opcodes/mips-opc.c index e47d1fd84ee..b151baea0c2 100644 --- a/opcodes/mips-opc.c +++ b/opcodes/mips-opc.c @@ -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 }, diff --git a/opcodes/mips16-opc.c b/opcodes/mips16-opc.c index 83663adc838..0ee71bee0c9 100644 --- a/opcodes/mips16-opc.c +++ b/opcodes/mips16-opc.c @@ -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 },