/* Print mips instructions for GDB, the GNU debugger, or for objdump.
- Copyright (C) 1989-2016 Free Software Foundation, Inc.
+ Copyright (C) 1989-2017 Free Software Foundation, Inc.
Contributed by Nobuyuki Hikichi(hikichi@sra.co.jp).
This file is part of the GNU opcodes library.
MA 02110-1301, USA. */
#include "sysdep.h"
-#include "dis-asm.h"
+#include "disassemble.h"
#include "libiberty.h"
#include "opcode/mips.h"
#include "opintl.h"
/* This entry, mips16, is here only for ISA/processor selection; do
not print its name. */
- { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS3, 0,
+ { "", 1, bfd_mach_mips16, CPU_MIPS16, ISA_MIPS64,
+ ASE_MIPS16E2 | ASE_MIPS16E2_MT,
mips_cp0_names_numeric, NULL, 0, mips_cp1_names_numeric,
mips_hwr_names_numeric },
};
opcode_ases |= ASE_XPA;
if (afl_ases & AFL_ASE_DSPR3)
opcode_ases |= ASE_DSPR3;
+ if (afl_ases & AFL_ASE_MIPS16E2)
+ opcode_ases |= ASE_MIPS16E2;
+ if ((afl_ases & (AFL_ASE_MIPS16E2 | AFL_ASE_MT))
+ == (AFL_ASE_MIPS16E2 | AFL_ASE_MT))
+ opcode_ases |= ASE_MIPS16E2_MT;
return opcode_ases;
}
Elf_Internal_Ehdr *header = elf_elfheader (abfd);
Elf_Internal_ABIFlags_v0 *abiflags = NULL;
- /* We won't ever get here if !BFD64, because we won't then have
- a MIPS/ELF BFD, however we need to guard against a link error
- in a `--enable-targets=...' configuration with a 32-bit host,
- where the MIPS target is a secondary. */
-#ifdef BFD64
+ /* We won't ever get here if !HAVE_BFD_MIPS_ELF_GET_ABIFLAGS,
+ because we won't then have a MIPS/ELF BFD, however we need
+ to guard against a link error in a `--enable-targets=...'
+ configuration with a 32-bit host where the MIPS target is
+ a secondary, or with MIPS/ECOFF configurations. */
+#ifdef HAVE_BFD_MIPS_ELF_GET_ABIFLAGS
abiflags = bfd_mips_elf_get_abiflags (abfd);
#endif
/* If an ELF "newabi" binary, use the n32/(n)64 GPR names. */
pcrel_op = (const struct mips_pcrel_operand *) operand;
info->target = mips_decode_pcrel_operand (pcrel_op, base_pc, uval);
- /* Preserve the ISA bit for the GDB disassembler,
- otherwise clear it. */
- if (info->flavour != bfd_target_unknown_flavour)
+ /* For jumps and branches clear the ISA bit except for
+ the GDB disassembler. */
+ if (pcrel_op->include_isa_bit
+ && info->flavour != bfd_target_unknown_flavour)
info->target &= -2;
(*info->print_address_func) (info->target, info);
infprintf (is, "$pc");
break;
+ case OP_REG28:
+ print_reg (info, opcode, OP_REG_GP, 28);
+ break;
+
case OP_VU0_SUFFIX:
case OP_VU0_MATCH_SUFFIX:
print_vu0_channel (info, operand, uval);
case OP_REPEAT_PREV_REG:
case OP_REPEAT_DEST_REG:
case OP_PC:
+ case OP_REG28:
case OP_VU0_SUFFIX:
case OP_VU0_MATCH_SUFFIX:
case OP_IMM_INDEX:
&& s[2] == 'H'
&& opcode->name[strlen (opcode->name) - 1] == '0')
{
- /* Coprocessor register 0 with sel field (MT ASE). */
+ /* Coprocessor register 0 with sel field. */
const struct mips_cp0sel_name *n;
unsigned int reg, sel;
const fprintf_ftype infprintf = info->fprintf_func;
void *is = info->stream;
const struct mips_operand *operand, *ext_operand;
+ unsigned short ext_size;
unsigned int uval;
bfd_vma baseaddr;
info->data_size = 1 << int_op->shift;
}
- if (operand->size == 26)
- uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
- else
+ ext_size = 0;
+ if (use_extend)
{
- /* Calculate the full field value. */
- uval = mips_extract_operand (operand, (extend << 16) | insn);
- if (use_extend)
+ ext_operand = decode_mips16_operand (type, TRUE);
+ if (ext_operand != operand
+ || (operand->type == OP_INT && operand->lsb == 0
+ && mips_opcode_32bit_p (opcode)))
{
- ext_operand = decode_mips16_operand (type, TRUE);
- if (ext_operand != operand)
- {
- operand = ext_operand;
- if (operand->size == 16)
- uval = (((extend & 0x1f) << 11) | (extend & 0x7e0)
- | (uval & 0x1f));
- else if (operand->size == 15)
- uval |= ((extend & 0xf) << 11) | (extend & 0x7f0);
- else
- uval = ((((extend >> 6) & 0x1f) | (extend & 0x20))
- & ((1U << operand->size) - 1));
- }
+ ext_size = ext_operand->size;
+ operand = ext_operand;
}
}
+ if (operand->size == 26)
+ uval = ((extend & 0x1f) << 21) | ((extend & 0x3e0) << 11) | insn;
+ else if (ext_size == 16 || ext_size == 9)
+ uval = ((extend & 0x1f) << 11) | (extend & 0x7e0) | (insn & 0x1f);
+ else if (ext_size == 15)
+ uval = ((extend & 0xf) << 11) | (extend & 0x7f0) | (insn & 0xf);
+ else if (ext_size == 6)
+ uval = ((extend >> 6) & 0x1f) | (extend & 0x20);
+ else
+ uval = mips_extract_operand (operand, (extend << 16) | insn);
+ if (ext_size == 9)
+ uval &= (1U << ext_size) - 1;
baseaddr = memaddr + 2;
if (operand->type == OP_PCREL)
struct mips_print_arg_state state;
void *is = info->stream;
bfd_boolean have_second;
+ bfd_boolean extend_only;
unsigned int second;
unsigned int first;
unsigned int full;
return -1;
}
+ extend_only = FALSE;
+
if (info->endian == BFD_ENDIAN_BIG)
first = bfd_getb16 (buffer);
else
{
enum match_kind match;
+ if (!opcode_is_member (op, mips_isa, mips_ase, mips_processor))
+ continue;
+
if (op->pinfo == INSN_MACRO
|| (no_aliases && (op->pinfo2 & INSN2_ALIAS)))
match = MATCH_NONE;
}
else if ((first & 0xf800) == 0xf000
&& have_second
+ && !extend_only
&& (second & op->mask) == op->match)
- match = MATCH_FULL;
+ {
+ if (op->pinfo2 & INSN2_SHORT_ONLY)
+ {
+ match = MATCH_NONE;
+ extend_only = TRUE;
+ }
+ else
+ match = MATCH_FULL;
+ }
else
match = MATCH_NONE;
++s;
continue;
}
- switch (match)
+ if (s[0] == 'N'
+ && s[1] == ','
+ && s[2] == 'O'
+ && op->name[strlen (op->name) - 1] == '0')
{
- case MATCH_FULL:
- print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
- second, TRUE, first, s[1] == '(');
- break;
- case MATCH_SHORT:
- print_mips16_insn_arg (info, &state, op, *s, memaddr,
- first, FALSE, 0, s[1] == '(');
- break;
- case MATCH_NONE: /* Stop the compiler complaining. */
- break;
+ /* Coprocessor register 0 with sel field. */
+ const struct mips_cp0sel_name *n;
+ const struct mips_operand *operand;
+ unsigned int reg, sel;
+
+ operand = decode_mips16_operand (*s, TRUE);
+ reg = mips_extract_operand (operand, (first << 16) | second);
+ s += 2;
+ operand = decode_mips16_operand (*s, TRUE);
+ sel = mips_extract_operand (operand, (first << 16) | second);
+
+ /* CP0 register including 'sel' code for mftc0, to be
+ printed textually if known. If not known, print both
+ CP0 register name and sel numerically since CP0 register
+ with sel 0 may have a name unrelated to register being
+ printed. */
+ n = lookup_mips_cp0sel_name (mips_cp0sel_names,
+ mips_cp0sel_names_len,
+ reg, sel);
+ if (n != NULL)
+ infprintf (is, "%s", n->name);
+ else
+ infprintf (is, "$%d,%d", reg, sel);
}
+ else
+ switch (match)
+ {
+ case MATCH_FULL:
+ print_mips16_insn_arg (info, &state, op, *s, memaddr + 2,
+ second, TRUE, first, s[1] == '(');
+ break;
+ case MATCH_SHORT:
+ print_mips16_insn_arg (info, &state, op, *s, memaddr,
+ first, FALSE, 0, s[1] == '(');
+ break;
+ case MATCH_NONE: /* Stop the compiler complaining. */
+ break;
+ }
}
/* Figure out branch instruction type and delay slot information. */
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\
+ no-aliases Use canonical instruction forms.\n"));
+
fprintf (stream, _("\n\
msa Recognize MSA instructions.\n"));