aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorMaciej W. Rozycki <macro@imgtec.com>2016-12-20 02:03:40 +0000
committerMaciej W. Rozycki <macro@imgtec.com>2016-12-20 11:56:32 +0000
commit7fd5392005624f8b0522d881aa94bbb470d68cd7 (patch)
tree680a9185f2e3f2c781b08b445357561cffc94077 /gas
parent4ebce1a0a5911e71aa2d00932ffb2126ff1f3633 (diff)
downloadgdb-7fd5392005624f8b0522d881aa94bbb470d68cd7.zip
gdb-7fd5392005624f8b0522d881aa94bbb470d68cd7.tar.gz
gdb-7fd5392005624f8b0522d881aa94bbb470d68cd7.tar.bz2
MIPS16: Switch to 32-bit opcode table interpretation
Switch to 32-bit MIPS16 opcode table entry interpretation, similar to how the microMIPS opcode table is handled, for both the `match' and `mask' fields, removing special casing for JAL and JALX instructions and their `a' and `i' operand codes throughout, while retaining automatic processing of extendable opcodes in assembly and disassembly. In assembly disallow size enforcement suffixes as appropriate: `.t' for both 32-bit instructions and macros and `.e' for macros only, making macro handling consistent with the microMIPS instruction set. In disassembly fully decode EXTEND prefixes prepended to unsupported instruction encodings (according to the ISA selection) rather than dumping them as hexadecimal data along with the following instruction, removing all special casing for the EXTEND prefix and making its handling rely on its opcode table entry, except where it is considered a part of an extendable instruction. include/ * opcode/mips.h (mips_opcode_32bit_p): New inline function. gas/ * config/tc-mips.c (micromips_insn_length): Use `mips_opcode_32bit_p'. (is_size_valid): Adjust description. (is_size_valid_16): New function. (validate_mips_insn): Use `mips_opcode_32bit_p' in MIPS16 operand decoding. (validate_mips16_insn): Remove `a' and `i' operand code special casing, use `mips_opcode_32bit_p' to determine instruction width. (append_insn): Adjust forced MIPS16 instruction size determination. (match_mips16_insn): Likewise. Don't shift the instruction's opcode with the `a' and `i' operand codes. Use `mips_opcode_32bit_p' in operand decoding. (match_mips16_insns): Check for forced instruction size's validity. (mips16_ip): Don't force instruction size in the `noautoextend' mode. * testsuite/gas/mips/mips16-jal-e.d: New test. * testsuite/gas/mips/mips16-jal-t.d: New test. * testsuite/gas/mips/mips16-macro-e.d: New test. * testsuite/gas/mips/mips16-macro-t.d: New test. * testsuite/gas/mips/mips16-jal-t.l: New stderr output. * testsuite/gas/mips/mips16-macro-e.l: New stderr output. * testsuite/gas/mips/mips16-macro-t.l: New stderr output. * testsuite/gas/mips/mips16-jal-e.s: New test source. * testsuite/gas/mips/mips16-jal-t.s: New test source. * testsuite/gas/mips/mips16-macro-e.s: New test source. * testsuite/gas/mips/mips16-macro-t.s: New test source. * testsuite/gas/mips/mips.exp: Run the new tests. opcodes/ * mips-dis.c (print_mips16_insn_arg): Always handle `extend' and `insn' together, with `extend' as the high-order 16 bits. (match_kind): New enum. (print_insn_mips16): Rework for 32-bit instruction matching. Do not dump EXTEND prefixes here. * mips16-opc.c (mips16_opcodes): Move "extend" entry to the end. Recode `match' and `mask' fields as 32-bit in absolute "jal" and "jalx" entries. binutils/ * testsuite/binutils-all/mips/mips16-extend-noinsn.d: Adjust test for separate EXTEND prefix disassembly.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog33
-rw-r--r--gas/config/tc-mips.c92
-rw-r--r--gas/testsuite/gas/mips/mips.exp4
-rw-r--r--gas/testsuite/gas/mips/mips16-jal-e.d12
-rw-r--r--gas/testsuite/gas/mips/mips16-jal-e.s8
-rw-r--r--gas/testsuite/gas/mips/mips16-jal-t.d3
-rw-r--r--gas/testsuite/gas/mips/mips16-jal-t.l3
-rw-r--r--gas/testsuite/gas/mips/mips16-jal-t.s8
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-e.d3
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-e.l56
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-e.s59
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-t.d3
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-t.l56
-rw-r--r--gas/testsuite/gas/mips/mips16-macro-t.s59
14 files changed, 375 insertions, 24 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index c1e0e1e..4b15c9f 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,5 +1,38 @@
2016-12-20 Maciej W. Rozycki <macro@imgtec.com>
+ * config/tc-mips.c (micromips_insn_length): Use
+ `mips_opcode_32bit_p'.
+ (is_size_valid): Adjust description.
+ (is_size_valid_16): New function.
+ (validate_mips_insn): Use `mips_opcode_32bit_p' in MIPS16
+ operand decoding.
+ (validate_mips16_insn): Remove `a' and `i' operand code special
+ casing, use `mips_opcode_32bit_p' to determine instruction
+ width.
+ (append_insn): Adjust forced MIPS16 instruction size
+ determination.
+ (match_mips16_insn): Likewise. Don't shift the instruction's
+ opcode with the `a' and `i' operand codes. Use
+ `mips_opcode_32bit_p' in operand decoding.
+ (match_mips16_insns): Check for forced instruction size's
+ validity.
+ (mips16_ip): Don't force instruction size in the `noautoextend'
+ mode.
+ * testsuite/gas/mips/mips16-jal-e.d: New test.
+ * testsuite/gas/mips/mips16-jal-t.d: New test.
+ * testsuite/gas/mips/mips16-macro-e.d: New test.
+ * testsuite/gas/mips/mips16-macro-t.d: New test.
+ * testsuite/gas/mips/mips16-jal-t.l: New stderr output.
+ * testsuite/gas/mips/mips16-macro-e.l: New stderr output.
+ * testsuite/gas/mips/mips16-macro-t.l: New stderr output.
+ * testsuite/gas/mips/mips16-jal-e.s: New test source.
+ * testsuite/gas/mips/mips16-jal-t.s: New test source.
+ * testsuite/gas/mips/mips16-macro-e.s: New test source.
+ * testsuite/gas/mips/mips16-macro-t.s: New test source.
+ * testsuite/gas/mips/mips.exp: Run the new tests.
+
+2016-12-20 Maciej W. Rozycki <macro@imgtec.com>
+
* testsuite/gas/mips/mips16-macro.l: New list test.
* testsuite/gas/mips/mips.exp: Run the new test.
diff --git a/gas/config/tc-mips.c b/gas/config/tc-mips.c
index 1241b9c..a68e267 100644
--- a/gas/config/tc-mips.c
+++ b/gas/config/tc-mips.c
@@ -2111,7 +2111,7 @@ mips_lookup_ase (const char *name)
static inline unsigned int
micromips_insn_length (const struct mips_opcode *mo)
{
- return (mo->mask >> 16) == 0 ? 2 : 4;
+ return mips_opcode_32bit_p (mo) ? 4 : 2;
}
/* Return the length of MIPS16 instruction OPCODE. */
@@ -3258,7 +3258,8 @@ is_opcode_valid_16 (const struct mips_opcode *mo)
}
/* Return TRUE if the size of the microMIPS opcode MO matches one
- explicitly requested. Always TRUE in the standard MIPS mode. */
+ explicitly requested. Always TRUE in the standard MIPS mode.
+ Use is_size_valid_16 for MIPS16 opcodes. */
static bfd_boolean
is_size_valid (const struct mips_opcode *mo)
@@ -3280,6 +3281,21 @@ is_size_valid (const struct mips_opcode *mo)
return forced_insn_length == micromips_insn_length (mo);
}
+/* Return TRUE if the size of the MIPS16 opcode MO matches one
+ explicitly requested. */
+
+static bfd_boolean
+is_size_valid_16 (const struct mips_opcode *mo)
+{
+ if (!forced_insn_length)
+ return TRUE;
+ if (mo->pinfo == INSN_MACRO)
+ return FALSE;
+ if (forced_insn_length == 2 && mips_opcode_32bit_p (mo))
+ return FALSE;
+ return TRUE;
+}
+
/* Return TRUE if the microMIPS opcode MO is valid for the delay slot
of the preceding instruction. Always TRUE in the standard MIPS mode.
@@ -3356,7 +3372,7 @@ validate_mips_insn (const struct mips_opcode *opcode,
default:
if (!decode_operand)
- operand = decode_mips16_operand (*s, FALSE);
+ operand = decode_mips16_operand (*s, mips_opcode_32bit_p (opcode));
else
operand = decode_operand (s);
if (!operand && opcode->pinfo != INSN_MACRO)
@@ -3414,18 +3430,9 @@ static int
validate_mips16_insn (const struct mips_opcode *opcode,
struct mips_operand_array *operands)
{
- if (opcode->args[0] == 'a' || opcode->args[0] == 'i')
- {
- /* In this case OPCODE defines the first 16 bits in a 32-bit jump
- instruction. Use TMP to describe the full instruction. */
- struct mips_opcode tmp;
+ unsigned long insn_bits = mips_opcode_32bit_p (opcode) ? 0xffffffff : 0xffff;
- tmp = *opcode;
- tmp.match <<= 16;
- tmp.mask <<= 16;
- return validate_mips_insn (&tmp, 0xffffffff, 0, operands);
- }
- return validate_mips_insn (opcode, 0xffff, 0, operands);
+ return validate_mips_insn (opcode, insn_bits, 0, operands);
}
/* The microMIPS version of validate_mips_insn. */
@@ -7357,9 +7364,23 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
}
else if (mips_opts.mips16 && *reloc_type > BFD_RELOC_UNUSED)
{
+ bfd_boolean require_unextended;
+ bfd_boolean require_extended;
symbolS *symbol;
offsetT offset;
+ if (forced_insn_length != 0)
+ {
+ require_unextended = forced_insn_length == 2;
+ require_extended = forced_insn_length == 4;
+ }
+ else
+ {
+ require_unextended = (mips_opts.noautoextend
+ && !mips_opcode_32bit_p (ip->insn_mo));
+ require_extended = 0;
+ }
+
/* We need to set up a variant frag. */
gas_assert (address_expr != NULL);
/* Pass any `O_symbol' expression unchanged as an `expr_section'
@@ -7378,7 +7399,7 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
add_relaxed_insn (ip, 4, 0,
RELAX_MIPS16_ENCODE
(*reloc_type - BFD_RELOC_UNUSED,
- forced_insn_length == 2, forced_insn_length == 4,
+ require_unextended, require_extended,
delayed_branch_p (&history[0]),
history[0].mips16_absolute_jump_p),
symbol, offset);
@@ -8039,9 +8060,17 @@ match_mips16_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
const char *args;
const struct mips_operand *operand;
const struct mips_operand *ext_operand;
+ int required_insn_length;
struct mips_arg_info arg;
int relax_char;
+ if (forced_insn_length)
+ required_insn_length = forced_insn_length;
+ else if (mips_opts.noautoextend && !mips_opcode_32bit_p (opcode))
+ required_insn_length = 2;
+ else
+ required_insn_length = 0;
+
create_insn (insn, opcode);
imm_expr.X_op = O_absent;
offset_expr.X_op = O_absent;
@@ -8097,13 +8126,13 @@ match_mips16_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
&value))
{
mips16_immed (NULL, 0, relax_char, *offset_reloc, value,
- forced_insn_length, &insn->insn_opcode);
+ required_insn_length, &insn->insn_opcode);
offset_expr.X_op = O_absent;
*offset_reloc = BFD_RELOC_UNUSED;
}
else if (relax_char && *offset_reloc != BFD_RELOC_UNUSED)
{
- if (forced_insn_length == 2)
+ if (required_insn_length == 2)
set_insn_error (0, _("invalid unextended operand value"));
forced_insn_length = 4;
insn->insn_opcode |= MIPS16_EXTEND;
@@ -8150,11 +8179,10 @@ match_mips16_insn (struct mips_cl_insn *insn, const struct mips_opcode *opcode,
case 'a':
case 'i':
*offset_reloc = BFD_RELOC_MIPS16_JMP;
- insn->insn_opcode <<= 16;
break;
}
- operand = decode_mips16_operand (c, FALSE);
+ operand = decode_mips16_operand (c, mips_opcode_32bit_p (opcode));
if (!operand)
abort ();
@@ -8315,11 +8343,13 @@ match_mips16_insns (struct mips_cl_insn *insn, const struct mips_opcode *first,
{
const struct mips_opcode *opcode;
bfd_boolean seen_valid_for_isa;
+ bfd_boolean seen_valid_for_size;
/* Search for a match, ignoring alternatives that don't satisfy the
current ISA. There are no separate entries for extended forms so
we deal with forced_length later. */
seen_valid_for_isa = FALSE;
+ seen_valid_for_size = FALSE;
opcode = first;
do
{
@@ -8327,8 +8357,12 @@ match_mips16_insns (struct mips_cl_insn *insn, const struct mips_opcode *first,
if (is_opcode_valid_16 (opcode))
{
seen_valid_for_isa = TRUE;
- if (match_mips16_insn (insn, opcode, tokens))
- return TRUE;
+ if (is_size_valid_16 (opcode))
+ {
+ seen_valid_for_size = TRUE;
+ if (match_mips16_insn (insn, opcode, tokens))
+ return TRUE;
+ }
}
++opcode;
}
@@ -8343,6 +8377,19 @@ match_mips16_insns (struct mips_cl_insn *insn, const struct mips_opcode *first,
return TRUE;
}
+ /* Handle the case where we didn't try to match an instruction because
+ all the alternatives were of the wrong size. */
+ if (!seen_valid_for_size)
+ {
+ if (forced_insn_length == 2)
+ set_insn_error
+ (0, _("unrecognized unextended version of MIPS16 opcode"));
+ else
+ set_insn_error
+ (0, _("unrecognized extended version of MIPS16 opcode"));
+ return TRUE;
+ }
+
return FALSE;
}
@@ -13845,9 +13892,6 @@ mips16_ip (char *str, struct mips_cl_insn *insn)
return;
}
- if (mips_opts.noautoextend && !forced_insn_length)
- forced_insn_length = 2;
-
*end = 0;
first = (struct mips_opcode *) hash_find (mips16_op_hash, str);
*end = c;
diff --git a/gas/testsuite/gas/mips/mips.exp b/gas/testsuite/gas/mips/mips.exp
index 101b653..ffc08a0 100644
--- a/gas/testsuite/gas/mips/mips.exp
+++ b/gas/testsuite/gas/mips/mips.exp
@@ -854,6 +854,8 @@ if { [istarget mips*-*-vxworks*] } {
}
run_dump_test "mips16-macro"
run_list_test "mips16-macro" "-32 -march=mips1"
+ run_dump_test "mips16-macro-t" "{{as} {-march=mips3}}"
+ run_dump_test "mips16-macro-e" "{{as} {-march=mips3}}"
# Check MIPS16e extensions
run_dump_test_arches "mips16e" [mips_arch_list_matching mips32 !micromips \
!mips32r6]
@@ -1318,6 +1320,8 @@ if { [istarget mips*-*-vxworks*] } {
run_dump_test "mips16-branch-unextended-1"
run_dump_test "mips16-branch-unextended-2"
+ run_dump_test "mips16-jal-t"
+ run_dump_test "mips16-jal-e"
run_dump_test "vxworks1"
run_dump_test "vxworks1-xgot"
diff --git a/gas/testsuite/gas/mips/mips16-jal-e.d b/gas/testsuite/gas/mips/mips16-jal-e.d
new file mode 100644
index 0000000..bbccb7c
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-jal-e.d
@@ -0,0 +1,12 @@
+#objdump: -d --prefix-addresses --show-raw-insn
+#name: MIPS16 explicit extended JAL instructions
+#as: -32
+
+.*: +file format .*mips.*
+
+Disassembly of section \.text:
+[0-9a-f]+ <[^>]*> 1c00 0000 jalx 00000000 <foo>
+[0-9a-f]+ <[^>]*> 6500 nop
+[0-9a-f]+ <[^>]*> 1800 0000 jal 00000000 <foo>
+[0-9a-f]+ <[^>]*> 6500 nop
+ \.\.\.
diff --git a/gas/testsuite/gas/mips/mips16-jal-e.s b/gas/testsuite/gas/mips/mips16-jal-e.s
new file mode 100644
index 0000000..9c18f5f
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-jal-e.s
@@ -0,0 +1,8 @@
+ .set mips16
+foo:
+ jalx.e bar
+ jal.e baz
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+ .align 4, 0
+ .space 16
diff --git a/gas/testsuite/gas/mips/mips16-jal-t.d b/gas/testsuite/gas/mips/mips16-jal-t.d
new file mode 100644
index 0000000..287f78d
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-jal-t.d
@@ -0,0 +1,3 @@
+#name: MIPS16 explicit unextended JAL instructions
+#as: -32
+#error-output: mips16-jal-t.l
diff --git a/gas/testsuite/gas/mips/mips16-jal-t.l b/gas/testsuite/gas/mips/mips16-jal-t.l
new file mode 100644
index 0000000..0f67828
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-jal-t.l
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:3: Error: unrecognized unextended version of MIPS16 opcode `jalx\.t bar'
+.*:4: Error: invalid operands `jal\.t baz'
diff --git a/gas/testsuite/gas/mips/mips16-jal-t.s b/gas/testsuite/gas/mips/mips16-jal-t.s
new file mode 100644
index 0000000..33d35ac
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-jal-t.s
@@ -0,0 +1,8 @@
+ .set mips16
+foo:
+ jalx.t bar
+ jal.t baz
+
+# Force some (non-delay-slot) zero bytes, to make 'objdump' print ...
+ .align 4, 0
+ .space 16
diff --git a/gas/testsuite/gas/mips/mips16-macro-e.d b/gas/testsuite/gas/mips/mips16-macro-e.d
new file mode 100644
index 0000000..464bac2
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-e.d
@@ -0,0 +1,3 @@
+#as: -32
+#name: MIPS16 explicit extended macros
+#error-output: mips16-macro-e.l
diff --git a/gas/testsuite/gas/mips/mips16-macro-e.l b/gas/testsuite/gas/mips/mips16-macro-e.l
new file mode 100644
index 0000000..225d9a9
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-e.l
@@ -0,0 +1,56 @@
+.*: Assembler messages:
+.*:4: Error: invalid operands `div\.e \$2,\$3,\$4'
+.*:5: Error: invalid operands `divu\.e \$3,\$4,\$5'
+.*:6: Error: invalid operands `ddiv\.e \$4,\$5,\$6'
+.*:7: Error: invalid operands `ddivu\.e \$5,\$6,\$7'
+.*:8: Error: invalid operands `rem\.e \$6,\$7,\$16'
+.*:9: Error: invalid operands `remu\.e \$6,\$7,\$17'
+.*:10: Error: invalid operands `drem\.e \$2,\$3,\$4'
+.*:11: Error: invalid operands `dremu\.e \$3,\$4,\$5'
+.*:12: Error: unrecognized extended version of MIPS16 opcode `mul\.e \$4,\$5,\$6'
+.*:13: Error: unrecognized extended version of MIPS16 opcode `dmul\.e \$5,\$6,\$7'
+.*:14: Error: invalid operands `subu\.e \$2,-32767'
+.*:15: Error: invalid operands `subu\.e \$3,16'
+.*:16: Error: invalid operands `subu\.e \$4,32768'
+.*:17: Error: invalid operands `subu\.e \$3,\$7,-16383'
+.*:18: Error: invalid operands `subu\.e \$4,\$16,4'
+.*:19: Error: invalid operands `subu\.e \$5,\$17,16384'
+.*:20: Error: invalid operands `dsubu\.e \$4,-32767'
+.*:21: Error: invalid operands `dsubu\.e \$6,6'
+.*:22: Error: invalid operands `dsubu\.e \$7,32768'
+.*:23: Error: invalid operands `dsubu\.e \$2,\$4,-16383'
+.*:24: Error: invalid operands `dsubu\.e \$3,\$7,8'
+.*:25: Error: invalid operands `dsubu\.e \$4,\$5,16384'
+.*:26: Error: unrecognized extended version of MIPS16 opcode `beq\.e \$2,\$3,1b'
+.*:27: Error: unrecognized extended version of MIPS16 opcode `bne\.e \$4,\$5,1b'
+.*:28: Error: unrecognized extended version of MIPS16 opcode `blt\.e \$6,\$7,1b'
+.*:29: Error: unrecognized extended version of MIPS16 opcode `bltu\.e \$16,\$17,1b'
+.*:30: Error: unrecognized extended version of MIPS16 opcode `ble\.e \$4,\$7,1b'
+.*:31: Error: unrecognized extended version of MIPS16 opcode `bleu\.e \$5,\$6,1b'
+.*:32: Error: unrecognized extended version of MIPS16 opcode `bge\.e \$4,\$16,1b'
+.*:33: Error: unrecognized extended version of MIPS16 opcode `bgeu\.e \$5,\$17,1b'
+.*:34: Error: unrecognized extended version of MIPS16 opcode `bgt\.e \$4,\$6,1b'
+.*:35: Error: unrecognized extended version of MIPS16 opcode `bgtu\.e \$5,\$7,1b'
+.*:36: Error: unrecognized extended version of MIPS16 opcode `beq\.e \$2,1,1b'
+.*:37: Error: unrecognized extended version of MIPS16 opcode `beq\.e \$3,65535,1b'
+.*:38: Error: unrecognized extended version of MIPS16 opcode `bne\.e \$4,1,1b'
+.*:39: Error: unrecognized extended version of MIPS16 opcode `bne\.e \$5,65535,1b'
+.*:40: Error: unrecognized extended version of MIPS16 opcode `blt\.e \$6,-32768,1b'
+.*:41: Error: unrecognized extended version of MIPS16 opcode `blt\.e \$7,32767,1b'
+.*:42: Error: unrecognized extended version of MIPS16 opcode `bltu\.e \$16,-32768,1b'
+.*:43: Error: unrecognized extended version of MIPS16 opcode `bltu\.e \$17,32767,1b'
+.*:44: Error: unrecognized extended version of MIPS16 opcode `ble\.e \$2,-32769,1b'
+.*:45: Error: unrecognized extended version of MIPS16 opcode `ble\.e \$3,32766,1b'
+.*:46: Error: unrecognized extended version of MIPS16 opcode `bleu\.e \$4,-32769,1b'
+.*:47: Error: unrecognized extended version of MIPS16 opcode `bleu\.e \$5,32766,1b'
+.*:48: Error: unrecognized extended version of MIPS16 opcode `bge\.e \$6,-32768,1b'
+.*:49: Error: unrecognized extended version of MIPS16 opcode `bge\.e \$7,32766,1b'
+.*:50: Error: unrecognized extended version of MIPS16 opcode `bgeu\.e \$16,-32768,1b'
+.*:51: Error: unrecognized extended version of MIPS16 opcode `bgeu\.e \$17,32767,1b'
+.*:52: Error: unrecognized extended version of MIPS16 opcode `bgt\.e \$2,-32769,1b'
+.*:53: Error: unrecognized extended version of MIPS16 opcode `bgt\.e \$3,32766,1b'
+.*:54: Error: unrecognized extended version of MIPS16 opcode `bgtu\.e \$4,-32769,1b'
+.*:55: Error: unrecognized extended version of MIPS16 opcode `bgtu\.e \$5,32766,1b'
+.*:56: Error: unrecognized extended version of MIPS16 opcode `abs\.e \$2'
+.*:57: Error: unrecognized extended version of MIPS16 opcode `abs\.e \$3,\$3'
+.*:58: Error: unrecognized extended version of MIPS16 opcode `abs\.e \$4,\$5'
diff --git a/gas/testsuite/gas/mips/mips16-macro-e.s b/gas/testsuite/gas/mips/mips16-macro-e.s
new file mode 100644
index 0000000..048ebda
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-e.s
@@ -0,0 +1,59 @@
+ .set mips16
+ .ent foo
+foo:
+ div.e $2,$3,$4
+ divu.e $3,$4,$5
+ ddiv.e $4,$5,$6
+ ddivu.e $5,$6,$7
+ rem.e $6,$7,$16
+ remu.e $6,$7,$17
+ drem.e $2,$3,$4
+ dremu.e $3,$4,$5
+ mul.e $4,$5,$6
+ dmul.e $5,$6,$7
+ subu.e $2,-32767
+ subu.e $3,16
+ subu.e $4,32768
+ subu.e $3,$7,-16383
+ subu.e $4,$16,4
+ subu.e $5,$17,16384
+ dsubu.e $4,-32767
+ dsubu.e $6,6
+ dsubu.e $7,32768
+ dsubu.e $2,$4,-16383
+ dsubu.e $3,$7,8
+ dsubu.e $4,$5,16384
+1: beq.e $2,$3,1b
+1: bne.e $4,$5,1b
+1: blt.e $6,$7,1b
+1: bltu.e $16,$17,1b
+1: ble.e $4,$7,1b
+1: bleu.e $5,$6,1b
+1: bge.e $4,$16,1b
+1: bgeu.e $5,$17,1b
+1: bgt.e $4,$6,1b
+1: bgtu.e $5,$7,1b
+1: beq.e $2,1,1b
+1: beq.e $3,65535,1b
+1: bne.e $4,1,1b
+1: bne.e $5,65535,1b
+1: blt.e $6,-32768,1b
+1: blt.e $7,32767,1b
+1: bltu.e $16,-32768,1b
+1: bltu.e $17,32767,1b
+1: ble.e $2,-32769,1b
+1: ble.e $3,32766,1b
+1: bleu.e $4,-32769,1b
+1: bleu.e $5,32766,1b
+1: bge.e $6,-32768,1b
+1: bge.e $7,32766,1b
+1: bgeu.e $16,-32768,1b
+1: bgeu.e $17,32767,1b
+1: bgt.e $2,-32769,1b
+1: bgt.e $3,32766,1b
+1: bgtu.e $4,-32769,1b
+1: bgtu.e $5,32766,1b
+ abs.e $2
+ abs.e $3,$3
+ abs.e $4,$5
+ .end foo
diff --git a/gas/testsuite/gas/mips/mips16-macro-t.d b/gas/testsuite/gas/mips/mips16-macro-t.d
new file mode 100644
index 0000000..104094d
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-t.d
@@ -0,0 +1,3 @@
+#as: -32
+#name: MIPS16 explicit unextended macros
+#error-output: mips16-macro-t.l
diff --git a/gas/testsuite/gas/mips/mips16-macro-t.l b/gas/testsuite/gas/mips/mips16-macro-t.l
new file mode 100644
index 0000000..9850cb3
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-t.l
@@ -0,0 +1,56 @@
+.*: Assembler messages:
+.*:4: Error: invalid operands `div\.t \$2,\$3,\$4'
+.*:5: Error: invalid operands `divu\.t \$3,\$4,\$5'
+.*:6: Error: invalid operands `ddiv\.t \$4,\$5,\$6'
+.*:7: Error: invalid operands `ddivu\.t \$5,\$6,\$7'
+.*:8: Error: invalid operands `rem\.t \$6,\$7,\$16'
+.*:9: Error: invalid operands `remu\.t \$6,\$7,\$17'
+.*:10: Error: invalid operands `drem\.t \$2,\$3,\$4'
+.*:11: Error: invalid operands `dremu\.t \$3,\$4,\$5'
+.*:12: Error: unrecognized unextended version of MIPS16 opcode `mul\.t \$4,\$5,\$6'
+.*:13: Error: unrecognized unextended version of MIPS16 opcode `dmul\.t \$5,\$6,\$7'
+.*:14: Error: invalid operands `subu\.t \$2,-32767'
+.*:15: Error: invalid operands `subu\.t \$3,16'
+.*:16: Error: invalid operands `subu\.t \$4,32768'
+.*:17: Error: invalid operands `subu\.t \$3,\$7,-16383'
+.*:18: Error: invalid operands `subu\.t \$4,\$16,4'
+.*:19: Error: invalid operands `subu\.t \$5,\$17,16384'
+.*:20: Error: invalid operands `dsubu\.t \$4,-32767'
+.*:21: Error: invalid operands `dsubu\.t \$6,6'
+.*:22: Error: invalid operands `dsubu\.t \$7,32768'
+.*:23: Error: invalid operands `dsubu\.t \$2,\$4,-16383'
+.*:24: Error: invalid operands `dsubu\.t \$3,\$7,8'
+.*:25: Error: invalid operands `dsubu\.t \$4,\$5,16384'
+.*:26: Error: unrecognized unextended version of MIPS16 opcode `beq\.t \$2,\$3,1b'
+.*:27: Error: unrecognized unextended version of MIPS16 opcode `bne\.t \$4,\$5,1b'
+.*:28: Error: unrecognized unextended version of MIPS16 opcode `blt\.t \$6,\$7,1b'
+.*:29: Error: unrecognized unextended version of MIPS16 opcode `bltu\.t \$16,\$17,1b'
+.*:30: Error: unrecognized unextended version of MIPS16 opcode `ble\.t \$4,\$7,1b'
+.*:31: Error: unrecognized unextended version of MIPS16 opcode `bleu\.t \$5,\$6,1b'
+.*:32: Error: unrecognized unextended version of MIPS16 opcode `bge\.t \$4,\$16,1b'
+.*:33: Error: unrecognized unextended version of MIPS16 opcode `bgeu\.t \$5,\$17,1b'
+.*:34: Error: unrecognized unextended version of MIPS16 opcode `bgt\.t \$4,\$6,1b'
+.*:35: Error: unrecognized unextended version of MIPS16 opcode `bgtu\.t \$5,\$7,1b'
+.*:36: Error: unrecognized unextended version of MIPS16 opcode `beq\.t \$2,1,1b'
+.*:37: Error: unrecognized unextended version of MIPS16 opcode `beq\.t \$3,65535,1b'
+.*:38: Error: unrecognized unextended version of MIPS16 opcode `bne\.t \$4,1,1b'
+.*:39: Error: unrecognized unextended version of MIPS16 opcode `bne\.t \$5,65535,1b'
+.*:40: Error: unrecognized unextended version of MIPS16 opcode `blt\.t \$6,-32768,1b'
+.*:41: Error: unrecognized unextended version of MIPS16 opcode `blt\.t \$7,32767,1b'
+.*:42: Error: unrecognized unextended version of MIPS16 opcode `bltu\.t \$16,-32768,1b'
+.*:43: Error: unrecognized unextended version of MIPS16 opcode `bltu\.t \$17,32767,1b'
+.*:44: Error: unrecognized unextended version of MIPS16 opcode `ble\.t \$2,-32769,1b'
+.*:45: Error: unrecognized unextended version of MIPS16 opcode `ble\.t \$3,32766,1b'
+.*:46: Error: unrecognized unextended version of MIPS16 opcode `bleu\.t \$4,-32769,1b'
+.*:47: Error: unrecognized unextended version of MIPS16 opcode `bleu\.t \$5,32766,1b'
+.*:48: Error: unrecognized unextended version of MIPS16 opcode `bge\.t \$6,-32768,1b'
+.*:49: Error: unrecognized unextended version of MIPS16 opcode `bge\.t \$7,32766,1b'
+.*:50: Error: unrecognized unextended version of MIPS16 opcode `bgeu\.t \$16,-32768,1b'
+.*:51: Error: unrecognized unextended version of MIPS16 opcode `bgeu\.t \$17,32767,1b'
+.*:52: Error: unrecognized unextended version of MIPS16 opcode `bgt\.t \$2,-32769,1b'
+.*:53: Error: unrecognized unextended version of MIPS16 opcode `bgt\.t \$3,32766,1b'
+.*:54: Error: unrecognized unextended version of MIPS16 opcode `bgtu\.t \$4,-32769,1b'
+.*:55: Error: unrecognized unextended version of MIPS16 opcode `bgtu\.t \$5,32766,1b'
+.*:56: Error: unrecognized unextended version of MIPS16 opcode `abs\.t \$2'
+.*:57: Error: unrecognized unextended version of MIPS16 opcode `abs\.t \$3,\$3'
+.*:58: Error: unrecognized unextended version of MIPS16 opcode `abs\.t \$4,\$5'
diff --git a/gas/testsuite/gas/mips/mips16-macro-t.s b/gas/testsuite/gas/mips/mips16-macro-t.s
new file mode 100644
index 0000000..cc04249
--- /dev/null
+++ b/gas/testsuite/gas/mips/mips16-macro-t.s
@@ -0,0 +1,59 @@
+ .set mips16
+ .ent foo
+foo:
+ div.t $2,$3,$4
+ divu.t $3,$4,$5
+ ddiv.t $4,$5,$6
+ ddivu.t $5,$6,$7
+ rem.t $6,$7,$16
+ remu.t $6,$7,$17
+ drem.t $2,$3,$4
+ dremu.t $3,$4,$5
+ mul.t $4,$5,$6
+ dmul.t $5,$6,$7
+ subu.t $2,-32767
+ subu.t $3,16
+ subu.t $4,32768
+ subu.t $3,$7,-16383
+ subu.t $4,$16,4
+ subu.t $5,$17,16384
+ dsubu.t $4,-32767
+ dsubu.t $6,6
+ dsubu.t $7,32768
+ dsubu.t $2,$4,-16383
+ dsubu.t $3,$7,8
+ dsubu.t $4,$5,16384
+1: beq.t $2,$3,1b
+1: bne.t $4,$5,1b
+1: blt.t $6,$7,1b
+1: bltu.t $16,$17,1b
+1: ble.t $4,$7,1b
+1: bleu.t $5,$6,1b
+1: bge.t $4,$16,1b
+1: bgeu.t $5,$17,1b
+1: bgt.t $4,$6,1b
+1: bgtu.t $5,$7,1b
+1: beq.t $2,1,1b
+1: beq.t $3,65535,1b
+1: bne.t $4,1,1b
+1: bne.t $5,65535,1b
+1: blt.t $6,-32768,1b
+1: blt.t $7,32767,1b
+1: bltu.t $16,-32768,1b
+1: bltu.t $17,32767,1b
+1: ble.t $2,-32769,1b
+1: ble.t $3,32766,1b
+1: bleu.t $4,-32769,1b
+1: bleu.t $5,32766,1b
+1: bge.t $6,-32768,1b
+1: bge.t $7,32766,1b
+1: bgeu.t $16,-32768,1b
+1: bgeu.t $17,32767,1b
+1: bgt.t $2,-32769,1b
+1: bgt.t $3,32766,1b
+1: bgtu.t $4,-32769,1b
+1: bgtu.t $5,32766,1b
+ abs.t $2
+ abs.t $3,$3
+ abs.t $4,$5
+ .end foo