aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2017-05-15 13:26:01 +0100
committerMaciej W. Rozycki <macro@imgtec.com>2017-05-15 13:57:10 +0100
commit25499ac7ee92bca177c9436383ee167d6a220066 (patch)
tree6c9e60dc1c4e7a5f4f55b382600043e60280bb95 /gas
parent20c59b843a90300e5f9e07add83f5c72c8f994a6 (diff)
downloadgdb-25499ac7ee92bca177c9436383ee167d6a220066.zip
gdb-25499ac7ee92bca177c9436383ee167d6a220066.tar.gz
gdb-25499ac7ee92bca177c9436383ee167d6a220066.tar.bz2
MIPS16e2: Add MIPS16e2 ASE support
Add MIPS16e2 ASE support as per the architecture specification[1], including in particular: 1. A new ELF ASE flag to mark MIPS16e2 binaries. 2. MIPS16e2 instruction assembly support, including a relaxation update to use LUI rather than an LI/SLL instruction pair for loading the high part of 32-bit addresses. 3. MIPS16e2 instruction disassembly support, including updated rules for extended forms of instructions that are now subdecoded and therefore do not alias to the original MIPS16 ISA revision instructions even for encodings that are not valid in the MIPS16e2 instruction set. Add `-mmips16e2' and `-mno-mips16e2' GAS command-line options and their corresponding `mips16e2' and `no-mips16e2' settings for the `.set' and `.module' pseudo-ops. Control the availability of the MT ASE subset of the MIPS16e2 instruction set with a combination of these controls and the preexisting MT ASE controls. Parts of this change by Matthew Fortune and Andrew Bennett. References: [1] "MIPS32 Architecture for Programmers: MIPS16e2 Application-Specific Extension Technical Reference Manual", Imagination Technologies Ltd., Document Number: MD01172, Revision 01.00, April 26, 2016 include/ * elf/mips.h (AFL_ASE_MIPS16E2): New macro. (AFL_ASE_MASK): Adjust accordingly. * opcode/mips.h: Document new operand codes defined. (mips_operand_type): Add OP_REG28 enum value. (INSN2_SHORT_ONLY): Update description. (ASE_MIPS16E2, ASE_MIPS16E2_MT): New macros. bfd/ * elfxx-mips.c (print_mips_ases): Handle MIPS16e2 ASE. opcodes/ * mips-dis.c (mips_arch_choices): Add ASE_MIPS16E2 and ASE_MIPS16E2_MT flags to the unnamed MIPS16 entry. (mips_convert_abiflags_ases): Handle the AFL_ASE_MIPS16E2 flag. (print_insn_arg) <OP_REG28>: Add handler. (validate_insn_args) <OP_REG28>: Handle. (print_mips16_insn_arg): Handle MIPS16 instructions that require 32-bit encoding and 9-bit immediates. (print_insn_mips16): Handle MIPS16 instructions that require 32-bit encoding and MFC0/MTC0 operand decoding. * mips16-opc.c (decode_mips16_operand) <'>', '9', 'G', 'N', 'O'> <'Q', 'T', 'b', 'c', 'd', 'r', 'u'>: Add handlers. (RD_C0, WR_C0, E2, E2MT): New macros. (mips16_opcodes): Add entries for MIPS16e2 instructions: GP-relative "addiu" and its "addu" spelling, "andi", "cache", "di", "ehb", "ei", "ext", "ins", GP-relative "lb", "lbu", "lh", "lhu", and "lw" instructions, "ll", "lui", "lwl", "lwr", "mfc0", "movn", "movtn", "movtz", "movz", "mtc0", "ori", "pause", "pref", "rdhwr", "sc", GP-relative "sb", "sh" and "sw" instructions, "swl", "swr", "sync" and its "sync_acquire", "sync_mb", "sync_release", "sync_rmb" and "sync_wmb" aliases, "xori", "dmt", "dvpe", "emt" and "evpe". Add split regular/extended entries for original MIPS16 ISA revision instructions whose extended forms are subdecoded in the MIPS16e2 ISA revision: "li", "sll" and "srl". binutils/ * readelf.c (print_mips_ases): Handle MIPS16e2 ASE. * NEWS: Mention MIPS16e2 ASE support. gas/ * config/tc-mips.c (RELAX_MIPS16_ENCODE): Add `e2' flag. (RELAX_MIPS16_E2): New macro. (RELAX_MIPS16_PIC, RELAX_MIPS16_SYM32, RELAX_MIPS16_NOMACRO) (RELAX_MIPS16_USER_SMALL, RELAX_MIPS16_USER_EXT) (RELAX_MIPS16_DSLOT, RELAX_MIPS16_JAL_DSLOT) (RELAX_MIPS16_EXTENDED, RELAX_MIPS16_MARK_EXTENDED) (RELAX_MIPS16_CLEAR_EXTENDED, RELAX_MIPS16_ALWAYS_EXTENDED) (RELAX_MIPS16_MARK_ALWAYS_EXTENDED) (RELAX_MIPS16_CLEAR_ALWAYS_EXTENDED, RELAX_MIPS16_MACRO) (RELAX_MIPS16_MARK_MACRO, RELAX_MIPS16_CLEAR_MACRO): Shift bits. (mips16_immed_extend): New prototype. (options): Add OPTION_MIPS16E2 and OPTION_NO_MIPS16E2 enum values. (md_longopts): Add "mmips16e2" and "mno-mips16e2" options. (mips_ases): Add "mips16e2" entry. (mips_set_ase): Handle MIPS16e2 ASE. (insn_insert_operand): Explicitly handle immediates with MIPS16 instructions that require 32-bit encoding. (is_opcode_valid_16): Pass enabled ASE bitmask on to `opcode_is_member'. (validate_mips_insn): Explicitly handle immediates with MIPS16 instructions that require 32-bit encoding. (operand_reg_mask) <OP_REG28>: Add handler. (match_reg28_operand): New function. (match_operand) <OP_REG28>: Add handler. (append_insn): Pass ASE_MIPS16E2 setting to RELAX_MIPS16_ENCODE. (match_mips16_insn): Handle MIPS16 instructions that require 32-bit encoding and `V' and `u' operand codes. (mips16_ip): Allow any characters except from `.' in opcodes. (mips16_immed_extend): Handle 9-bit immediates. Do not shuffle immediates whose width is not one of these listed. (md_estimate_size_before_relax): Handle MIPS16e2 relaxation. (mips_relax_frag): Likewise. (md_convert_frag): Likewise. (mips_convert_ase_flags): Handle MIPS16e2 ASE. * doc/as.texinfo (Target MIPS options): Add `-mmips16e2' and `-mno-mips16e2' options. (-mmips16e2, -mno-mips16e2): New options. * doc/c-mips.texi (MIPS Options): Add `-mmips16e2' and `-mno-mips16e2' options. (MIPS ASE Instruction Generation Overrides): Add `.set mips16e2' and `.set nomips16e2'.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog48
-rw-r--r--gas/config/tc-mips.c160
-rw-r--r--gas/doc/as.texinfo7
-rw-r--r--gas/doc/c-mips.texi16
4 files changed, 187 insertions, 44 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c9ed98b..00b4742 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,4 +1,52 @@
2017-05-15 Maciej W. Rozycki <macro@imgtec.com>
+ Matthew Fortune <matthew.fortune@imgtec.com>
+ Andrew Bennett <andrew.bennett@imgtec.com>
+
+ * config/tc-mips.c (RELAX_MIPS16_ENCODE): Add `e2' flag.
+ (RELAX_MIPS16_E2): New macro.
+ (RELAX_MIPS16_PIC, RELAX_MIPS16_SYM32, RELAX_MIPS16_NOMACRO)
+ (RELAX_MIPS16_USER_SMALL, RELAX_MIPS16_USER_EXT)
+ (RELAX_MIPS16_DSLOT, RELAX_MIPS16_JAL_DSLOT)
+ (RELAX_MIPS16_EXTENDED, RELAX_MIPS16_MARK_EXTENDED)
+ (RELAX_MIPS16_CLEAR_EXTENDED, RELAX_MIPS16_ALWAYS_EXTENDED)
+ (RELAX_MIPS16_MARK_ALWAYS_EXTENDED)
+ (RELAX_MIPS16_CLEAR_ALWAYS_EXTENDED, RELAX_MIPS16_MACRO)
+ (RELAX_MIPS16_MARK_MACRO, RELAX_MIPS16_CLEAR_MACRO): Shift bits.
+ (mips16_immed_extend): New prototype.
+ (options): Add OPTION_MIPS16E2 and OPTION_NO_MIPS16E2 enum
+ values.
+ (md_longopts): Add "mmips16e2" and "mno-mips16e2" options.
+ (mips_ases): Add "mips16e2" entry.
+ (mips_set_ase): Handle MIPS16e2 ASE.
+ (insn_insert_operand): Explicitly handle immediates with MIPS16
+ instructions that require 32-bit encoding.
+ (is_opcode_valid_16): Pass enabled ASE bitmask on to
+ `opcode_is_member'.
+ (validate_mips_insn): Explicitly handle immediates with MIPS16
+ instructions that require 32-bit encoding.
+ (operand_reg_mask) <OP_REG28>: Add handler.
+ (match_reg28_operand): New function.
+ (match_operand) <OP_REG28>: Add handler.
+ (append_insn): Pass ASE_MIPS16E2 setting to RELAX_MIPS16_ENCODE.
+ (match_mips16_insn): Handle MIPS16 instructions that require
+ 32-bit encoding and `V' and `u' operand codes.
+ (mips16_ip): Allow any characters except from `.' in opcodes.
+ (mips16_immed_extend): Handle 9-bit immediates. Do not shuffle
+ immediates whose width is not one of these listed.
+ (md_estimate_size_before_relax): Handle MIPS16e2 relaxation.
+ (mips_relax_frag): Likewise.
+ (md_convert_frag): Likewise.
+ (mips_convert_ase_flags): Handle MIPS16e2 ASE.
+
+ * doc/as.texinfo (Target MIPS options): Add `-mmips16e2' and
+ `-mno-mips16e2' options.
+ (-mmips16e2, -mno-mips16e2): New options.
+ * doc/c-mips.texi (MIPS Options): Add `-mmips16e2' and
+ `-mno-mips16e2' options.
+ (MIPS ASE Instruction Generation Overrides): Add `.set mips16e2'
+ and `.set nomips16e2'.
+
+2017-05-15 Maciej W. Rozycki <macro@imgtec.com>
* config/tc-mips.c (match_int_operand): Call
`match_out_of_range' before returning failure for 0x8000-0xffff
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index beb4d46..7e927b2 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -1130,38 +1130,40 @@ static bfd_boolean mips_ignore_branch_isa;
store whether this is known to be a branch to a different section,
whether we have tried to relax this frag yet, and whether we have
ever extended a PC relative fragment because of a shift count. */
-#define RELAX_MIPS16_ENCODE(type, pic, sym32, nomacro, \
+#define RELAX_MIPS16_ENCODE(type, e2, pic, sym32, nomacro, \
small, ext, \
dslot, jal_dslot) \
(0x80000000 \
| ((type) & 0xff) \
- | ((pic) ? 0x100 : 0) \
- | ((sym32) ? 0x200 : 0) \
- | ((nomacro) ? 0x400 : 0) \
- | ((small) ? 0x800 : 0) \
- | ((ext) ? 0x1000 : 0) \
- | ((dslot) ? 0x2000 : 0) \
- | ((jal_dslot) ? 0x4000 : 0))
+ | ((e2) ? 0x100 : 0) \
+ | ((pic) ? 0x200 : 0) \
+ | ((sym32) ? 0x400 : 0) \
+ | ((nomacro) ? 0x800 : 0) \
+ | ((small) ? 0x1000 : 0) \
+ | ((ext) ? 0x2000 : 0) \
+ | ((dslot) ? 0x4000 : 0) \
+ | ((jal_dslot) ? 0x8000 : 0))
#define RELAX_MIPS16_P(i) (((i) & 0xc0000000) == 0x80000000)
#define RELAX_MIPS16_TYPE(i) ((i) & 0xff)
-#define RELAX_MIPS16_PIC(i) (((i) & 0x100) != 0)
-#define RELAX_MIPS16_SYM32(i) (((i) & 0x200) != 0)
-#define RELAX_MIPS16_NOMACRO(i) (((i) & 0x400) != 0)
-#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x800) != 0)
-#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x1000) != 0)
-#define RELAX_MIPS16_DSLOT(i) (((i) & 0x2000) != 0)
-#define RELAX_MIPS16_JAL_DSLOT(i) (((i) & 0x4000) != 0)
-
-#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x8000) != 0)
-#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x8000)
-#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) & ~0x8000)
-#define RELAX_MIPS16_ALWAYS_EXTENDED(i) (((i) & 0x10000) != 0)
-#define RELAX_MIPS16_MARK_ALWAYS_EXTENDED(i) ((i) | 0x10000)
-#define RELAX_MIPS16_CLEAR_ALWAYS_EXTENDED(i) ((i) & ~0x10000)
-#define RELAX_MIPS16_MACRO(i) (((i) & 0x20000) != 0)
-#define RELAX_MIPS16_MARK_MACRO(i) ((i) | 0x20000)
-#define RELAX_MIPS16_CLEAR_MACRO(i) ((i) & ~0x20000)
+#define RELAX_MIPS16_E2(i) (((i) & 0x100) != 0)
+#define RELAX_MIPS16_PIC(i) (((i) & 0x200) != 0)
+#define RELAX_MIPS16_SYM32(i) (((i) & 0x400) != 0)
+#define RELAX_MIPS16_NOMACRO(i) (((i) & 0x800) != 0)
+#define RELAX_MIPS16_USER_SMALL(i) (((i) & 0x1000) != 0)
+#define RELAX_MIPS16_USER_EXT(i) (((i) & 0x2000) != 0)
+#define RELAX_MIPS16_DSLOT(i) (((i) & 0x4000) != 0)
+#define RELAX_MIPS16_JAL_DSLOT(i) (((i) & 0x8000) != 0)
+
+#define RELAX_MIPS16_EXTENDED(i) (((i) & 0x10000) != 0)
+#define RELAX_MIPS16_MARK_EXTENDED(i) ((i) | 0x10000)
+#define RELAX_MIPS16_CLEAR_EXTENDED(i) ((i) & ~0x10000)
+#define RELAX_MIPS16_ALWAYS_EXTENDED(i) (((i) & 0x20000) != 0)
+#define RELAX_MIPS16_MARK_ALWAYS_EXTENDED(i) ((i) | 0x20000)
+#define RELAX_MIPS16_CLEAR_ALWAYS_EXTENDED(i) ((i) & ~0x20000)
+#define RELAX_MIPS16_MACRO(i) (((i) & 0x40000) != 0)
+#define RELAX_MIPS16_MARK_MACRO(i) ((i) | 0x40000)
+#define RELAX_MIPS16_CLEAR_MACRO(i) ((i) & ~0x40000)
/* For microMIPS code, we use relaxation similar to one we use for
MIPS16 code. Some instructions that take immediate values support
@@ -1341,6 +1343,7 @@ static void macro (struct mips_cl_insn *ip, char *str);
static void mips16_macro (struct mips_cl_insn * ip);
static void mips_ip (char *str, struct mips_cl_insn * ip);
static void mips16_ip (char *str, struct mips_cl_insn * ip);
+static unsigned long mips16_immed_extend (offsetT, unsigned int);
static void mips16_immed
(const char *, unsigned int, int, bfd_reloc_code_real_type, offsetT,
unsigned int, unsigned long *);
@@ -1455,6 +1458,8 @@ enum options
OPTION_NO_MICROMIPS,
OPTION_MCU,
OPTION_NO_MCU,
+ OPTION_MIPS16E2,
+ OPTION_NO_MIPS16E2,
OPTION_COMPAT_ARCH_BASE,
OPTION_M4650,
OPTION_NO_M4650,
@@ -1575,6 +1580,8 @@ struct option md_longopts[] =
{"mno-msa", no_argument, NULL, OPTION_NO_MSA},
{"mxpa", no_argument, NULL, OPTION_XPA},
{"mno-xpa", no_argument, NULL, OPTION_NO_XPA},
+ {"mmips16e2", no_argument, NULL, OPTION_MIPS16E2},
+ {"mno-mips16e2", no_argument, NULL, OPTION_NO_MIPS16E2},
/* Old-style architecture options. Don't add more of these. */
{"m4650", no_argument, NULL, OPTION_M4650},
@@ -1757,6 +1764,11 @@ static const struct mips_ase mips_ases[] = {
OPTION_XPA, OPTION_NO_XPA,
2, 2, -1, -1,
-1 },
+
+ { "mips16e2", ASE_MIPS16E2, 0,
+ OPTION_MIPS16E2, OPTION_NO_MIPS16E2,
+ 2, 2, -1, -1,
+ 6 },
};
/* The set of ASEs that require -mfp64. */
@@ -2120,6 +2132,13 @@ mips_set_ase (const struct mips_ase *ase, struct mips_set_options *opts,
opts->ase &= ~mask;
if (enabled_p)
opts->ase |= ase->flags;
+
+ if ((opts->ase & (ASE_MIPS16E2 | ASE_MT)) == (ASE_MIPS16E2 | ASE_MT))
+ {
+ opts->ase |= ASE_MIPS16E2_MT;
+ mask |= ASE_MIPS16E2_MT;
+ }
+
return mask;
}
@@ -2226,7 +2245,12 @@ static inline void
insn_insert_operand (struct mips_cl_insn *insn,
const struct mips_operand *operand, unsigned int uval)
{
- insn->insn_opcode = mips_insert_operand (operand, insn->insn_opcode, uval);
+ if (mips_opts.mips16
+ && operand->type == OP_INT && operand->lsb == 0
+ && mips_opcode_32bit_p (insn->insn_mo))
+ insn->insn_opcode |= mips16_immed_extend (uval, operand->size);
+ else
+ insn->insn_opcode = mips_insert_operand (operand, insn->insn_opcode, uval);
}
/* Extract the value of OPERAND from INSN. */
@@ -3286,7 +3310,16 @@ is_opcode_valid (const struct mips_opcode *mo)
static bfd_boolean
is_opcode_valid_16 (const struct mips_opcode *mo)
{
- return opcode_is_member (mo, mips_opts.isa, 0, mips_opts.arch);
+ int isa = mips_opts.isa;
+ int ase = mips_opts.ase;
+ unsigned int i;
+
+ if (ISA_HAS_64BIT_REGS (isa))
+ for (i = 0; i < ARRAY_SIZE (mips_ases); i++)
+ if ((ase & mips_ases[i].flags) == mips_ases[i].flags)
+ ase |= mips_ases[i].flags64;
+
+ return opcode_is_member (mo, isa, ase, mips_opts.arch);
}
/* Return TRUE if the size of the microMIPS opcode MO matches one
@@ -3417,7 +3450,11 @@ validate_mips_insn (const struct mips_opcode *opcode,
}
gas_assert (opno < MAX_OPERANDS);
operands->operand[opno] = operand;
- if (operand && operand->type != OP_VU0_MATCH_SUFFIX)
+ if (!decode_operand && operand
+ && operand->type == OP_INT && operand->lsb == 0
+ && mips_opcode_32bit_p (opcode))
+ used_bits |= mips16_immed_extend (-1, operand->size);
+ else if (operand && operand->type != OP_VU0_MATCH_SUFFIX)
{
used_bits = mips_insert_operand (operand, used_bits, -1);
if (operand->type == OP_MDMX_IMM_REG)
@@ -4501,6 +4538,9 @@ operand_reg_mask (const struct mips_cl_insn *insn,
case OP_IMM_INDEX:
abort ();
+ case OP_REG28:
+ return 1 << 28;
+
case OP_REG:
case OP_OPTIONAL_REG:
{
@@ -5795,6 +5835,23 @@ match_pc_operand (struct mips_arg_info *arg)
return FALSE;
}
+/* OP_REG28 matcher. */
+
+static bfd_boolean
+match_reg28_operand (struct mips_arg_info *arg)
+{
+ unsigned int regno;
+
+ if (arg->token->type == OT_REG
+ && match_regno (arg, OP_REG_GP, arg->token->u.regno, &regno)
+ && regno == GP)
+ {
+ ++arg->token;
+ return TRUE;
+ }
+ return FALSE;
+}
+
/* OP_NON_ZERO_REG matcher. */
static bfd_boolean
@@ -6079,6 +6136,9 @@ match_operand (struct mips_arg_info *arg,
case OP_PC:
return match_pc_operand (arg);
+ case OP_REG28:
+ return match_reg28_operand (arg);
+
case OP_VU0_SUFFIX:
return match_vu0_suffix_operand (arg, operand, FALSE);
@@ -7452,6 +7512,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
add_relaxed_insn (ip, 12, 0,
RELAX_MIPS16_ENCODE
(*reloc_type - BFD_RELOC_UNUSED,
+ mips_opts.ase & ASE_MIPS16E2,
mips_pic != NO_PIC,
HAVE_32BIT_SYMBOLS,
mips_opts.warn_about_macros,
@@ -8194,7 +8255,7 @@ match_mips16_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
{
if (required_insn_length == 2)
set_insn_error (0, _("invalid unextended operand value"));
- else
+ else if (!mips_opcode_32bit_p (opcode))
{
forced_insn_length = 4;
insn->insn_opcode |= MIPS16_EXTEND;
@@ -8228,6 +8289,8 @@ match_mips16_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
case 'A':
case 'B':
case 'E':
+ case 'V':
+ case 'u':
relax_char = c;
break;
@@ -13923,7 +13986,7 @@ mips16_ip (char *str, struct mips_cl_insn *insn)
struct mips_operand_token *tokens;
unsigned int l;
- for (s = str; ISLOWER (*s); ++s)
+ for (s = str; *s != '\0' && *s != '.' && *s != ' '; ++s)
;
end = s;
c = *end;
@@ -13954,8 +14017,6 @@ mips16_ip (char *str, struct mips_cl_insn *insn)
break;
else if (*s++ == ' ')
break;
- /* Fall through. */
- default:
set_insn_error (0, _("unrecognized opcode"));
return;
}
@@ -13988,7 +14049,10 @@ static unsigned long
mips16_immed_extend (offsetT val, unsigned int nbits)
{
int extval;
- if (nbits == 16)
+
+ extval = 0;
+ val &= (1U << nbits) - 1;
+ if (nbits == 16 || nbits == 9)
{
extval = ((val >> 11) & 0x1f) | (val & 0x7e0);
val &= 0x1f;
@@ -13998,7 +14062,7 @@ mips16_immed_extend (offsetT val, unsigned int nbits)
extval = ((val >> 11) & 0xf) | (val & 0x7f0);
val &= 0xf;
}
- else
+ else if (nbits == 6)
{
extval = ((val & 0x1f) << 6) | (val & 0x20);
val = 0;
@@ -17703,7 +17767,7 @@ md_estimate_size_before_relax (fragS *fragp, asection *segtype)
/* We don't want to modify the EXTENDED bit here; it might get us
into infinite loops. We change it only in mips_relax_frag(). */
if (RELAX_MIPS16_MACRO (fragp->fr_subtype))
- return 12;
+ return RELAX_MIPS16_E2 (fragp->fr_subtype) ? 8 : 12;
else
return RELAX_MIPS16_EXTENDED (fragp->fr_subtype) ? 4 : 2;
}
@@ -17961,7 +18025,7 @@ mips_relax_frag (asection *sec, fragS *fragp, long stretch)
if (RELAX_MIPS16_MACRO (fragp->fr_subtype))
{
fragp->fr_subtype = RELAX_MIPS16_CLEAR_MACRO (fragp->fr_subtype);
- return -10;
+ return RELAX_MIPS16_E2 (fragp->fr_subtype) ? -6 : -10;
}
else if (RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
{
@@ -17977,7 +18041,7 @@ mips_relax_frag (asection *sec, fragS *fragp, long stretch)
{
fragp->fr_subtype = RELAX_MIPS16_CLEAR_MACRO (fragp->fr_subtype);
fragp->fr_subtype = RELAX_MIPS16_MARK_EXTENDED (fragp->fr_subtype);
- return -8;
+ return RELAX_MIPS16_E2 (fragp->fr_subtype) ? -4 : -8;
}
else if (!RELAX_MIPS16_EXTENDED (fragp->fr_subtype))
{
@@ -17995,12 +18059,12 @@ mips_relax_frag (asection *sec, fragS *fragp, long stretch)
{
fragp->fr_subtype = RELAX_MIPS16_CLEAR_EXTENDED (fragp->fr_subtype);
fragp->fr_subtype = RELAX_MIPS16_MARK_MACRO (fragp->fr_subtype);
- return 8;
+ return RELAX_MIPS16_E2 (fragp->fr_subtype) ? 4 : 8;
}
else
{
fragp->fr_subtype = RELAX_MIPS16_MARK_MACRO (fragp->fr_subtype);
- return 10;
+ return RELAX_MIPS16_E2 (fragp->fr_subtype) ? 6 : 10;
}
}
@@ -18575,10 +18639,13 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
unsigned long reg;
unsigned long new;
unsigned long op;
+ bfd_boolean e2;
gas_assert (type == 'A' || type == 'B' || type == 'E');
gas_assert (RELAX_MIPS16_SYM32 (fragp->fr_subtype));
+ e2 = RELAX_MIPS16_E2 (fragp->fr_subtype);
+
if (need_reloc)
{
fixS *fixp;
@@ -18591,7 +18658,7 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
fixp->fx_file = fragp->fr_file;
fixp->fx_line = fragp->fr_line;
- fixp = fix_new (fragp, buf - fragp->fr_literal + 8, 4,
+ fixp = fix_new (fragp, buf - fragp->fr_literal + (e2 ? 4 : 8), 4,
fragp->fr_symbol, fragp->fr_offset,
FALSE, BFD_RELOC_MIPS16_LO16);
fixp->fx_file = fragp->fr_file;
@@ -18628,15 +18695,18 @@ md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT asec, fragS *fragp)
abort ();
}
- new = 0xf0006800 | (reg << 8); /* LI */
+ new = (e2 ? 0xf0006820 : 0xf0006800) | (reg << 8); /* LUI/LI */
new |= mips16_immed_extend ((val + 0x8000) >> 16, 16);
buf = write_compressed_insn (buf, new, 4);
- new = 0xf4003000 | (reg << 8) | (reg << 5); /* SLL */
- buf = write_compressed_insn (buf, new, 4);
+ if (!e2)
+ {
+ new = 0xf4003000 | (reg << 8) | (reg << 5); /* SLL */
+ buf = write_compressed_insn (buf, new, 4);
+ }
op |= mips16_immed_extend (val, 16);
buf = write_compressed_insn (buf, op, 4);
- fragp->fr_fix += 12;
+ fragp->fr_fix += e2 ? 8 : 12;
}
else
{
@@ -18866,6 +18936,8 @@ mips_convert_ase_flags (int ase)
ext_ases |= AFL_ASE_MSA;
if (ase & ASE_XPA)
ext_ases |= AFL_ASE_XPA;
+ if (ase & ASE_MIPS16E2)
+ ext_ases |= file_ase_mips16 ? AFL_ASE_MIPS16E2 : 0;
return ext_ases;
}
diff --git a/gas/doc/as.texinfo b/gas/doc/as.texinfo
index 27d0c68..e0637c7 100644
--- a/gas/doc/as.texinfo
+++ b/gas/doc/as.texinfo
@@ -420,6 +420,7 @@ gcc(1), ld(1), and the Info entries for @file{binutils} and @file{ld}.
[@b{-mnan=@var{encoding}}]
[@b{-trap}] [@b{-no-break}] [@b{-break}] [@b{-no-trap}]
[@b{-mips16}] [@b{-no-mips16}]
+ [@b{-mmips16e2}] [@b{-mno-mips16e2}]
[@b{-mmicromips}] [@b{-mno-micromips}]
[@b{-msmartmips}] [@b{-mno-smartmips}]
[@b{-mips3d}] [@b{-no-mips3d}]
@@ -1455,6 +1456,12 @@ Generate code for the MIPS 16 processor. This is equivalent to putting
@code{.module mips16} at the start of the assembly file. @samp{-no-mips16}
turns off this option.
+@item -mmips16e2
+@itemx -mno-mips16e2
+Enable the use of MIPS16e2 instructions in MIPS16 mode. This is equivalent
+to putting @code{.module mips16e2} at the start of the assembly file.
+@samp{-mno-mips16e2} turns off this option.
+
@item -mmicromips
@itemx -mno-micromips
Generate code for the microMIPS processor. This is equivalent to putting
diff --git a/gas/doc/c-mips.texi b/gas/doc/c-mips.texi
index e5d00b2..c2d9b7a 100644
--- a/gas/doc/c-mips.texi
+++ b/gas/doc/c-mips.texi
@@ -151,6 +151,12 @@ Generate code for the MIPS 16 processor. This is equivalent to putting
@code{.module mips16} at the start of the assembly file. @samp{-no-mips16}
turns off this option.
+@item -mmips16e2
+@itemx -mno-mips16e2
+Enable the use of MIPS16e2 instructions in MIPS16 mode. This is equivalent
+to putting @code{.module mips16e2} at the start of the assembly file.
+@samp{-mno-mips16e2} turns off this option.
+
@item -mmicromips
@itemx -mno-micromips
Generate code for the microMIPS processor. This is equivalent to putting
@@ -1094,6 +1100,16 @@ The directive @code{.set xpa} makes the assembler accept instructions
from the XPA Extension from that point on in the assembly. The
@code{.set noxpa} directive prevents XPA instructions from being accepted.
+@cindex MIPS16e2 instruction generation override
+@kindex @code{.set mips16e2}
+@kindex @code{.set nomips16e2}
+The directive @code{.set mips16e2} makes the assembler accept instructions
+from the MIPS16e2 Application Specific Extension from that point on in the
+assembly, whenever in MIPS16 mode. The @code{.set nomips16e2} prevents
+MIPS16e2 instructions from being accepted, in MIPS16 mode. Neither
+directive affects the state of MIPS16 mode being active itself which has
+separate controls.
+
Traditional MIPS assemblers do not support these directives.
@node MIPS Floating-Point