aboutsummaryrefslogtreecommitdiff
path: root/opcodes
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2017-06-28 02:07:36 +0100
committerMaciej W. Rozycki <macro@imgtec.com>2017-06-28 02:07:36 +0100
commit38bf472a15210c222bb3885820e763c47760a704 (patch)
tree71d1b3d93f6a6f8d85fb4b1ff4a099fcf468b6a3 /opcodes
parent9991e9d77fe04c4fde9b88964c6f25119a781e0d (diff)
downloadfsf-binutils-gdb-38bf472a15210c222bb3885820e763c47760a704.zip
fsf-binutils-gdb-38bf472a15210c222bb3885820e763c47760a704.tar.gz
fsf-binutils-gdb-38bf472a15210c222bb3885820e763c47760a704.tar.bz2
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) <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.
Diffstat (limited to 'opcodes')
-rw-r--r--opcodes/ChangeLog21
-rw-r--r--opcodes/mips-dis.c180
-rw-r--r--opcodes/mips-formats.h7
-rw-r--r--opcodes/mips-opc.c11
-rw-r--r--opcodes/mips16-opc.c6
5 files changed, 152 insertions, 73 deletions
diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog
index 5371bbb..64bc5fa6 100644
--- a/opcodes/ChangeLog
+++ b/opcodes/ChangeLog
@@ -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
diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c
index b541e03..e19d59a 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 5277a83..7c8ea4e 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 e47d1fd..b151bae 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 83663ad..0ee71be 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 },