aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorZack Weinberg <zackw@panix.com>2005-03-15 20:38:00 +0000
committerZack Weinberg <zackw@panix.com>2005-03-15 20:38:00 +0000
commitb05fe5cf682fff1677b2f8a9bf4328cdeb401e5b (patch)
tree84f32269b26f9dee9b455b922d2c4649abd44387 /gas
parent957d91c17826944963506e9479ac670b09d35a24 (diff)
downloadbinutils-b05fe5cf682fff1677b2f8a9bf4328cdeb401e5b.zip
binutils-b05fe5cf682fff1677b2f8a9bf4328cdeb401e5b.tar.gz
binutils-b05fe5cf682fff1677b2f8a9bf4328cdeb401e5b.tar.bz2
* config/tc-arm.c (do_mla): Rename to do_mlas, take second
is_mls parameter; do not diagnose Rm==Rd when is_mls. (do_mla, do_mls, five_bit_unsigned_immediate, bfci_lsb_and_width) (do_bfc, do_bfi, do_bfx, do_rbit, do_mov16, do_ldsttv4): New functions. (insns): Add ARMv6T2 instructions: bfc bfi mls movw movt rbit sbfx ubfx ldrht ldrsht ldrsbt strht. (arm_archs): Add V6T2 variants. testsuite: * gas/arm/archv6t2.d, gas/arm/archv6t2.s: New dump test. * gas/arm/archv6t2-bad.l, gas/arm/archv6t2-bad.l: New errors test. * gas/arm/arm.exp: Run them.
Diffstat (limited to 'gas')
-rw-r--r--gas/ChangeLog10
-rw-r--r--gas/config/tc-arm.c395
-rw-r--r--gas/testsuite/ChangeLog6
-rw-r--r--gas/testsuite/gas/arm/archv6t2-bad.l38
-rw-r--r--gas/testsuite/gas/arm/archv6t2-bad.s53
-rw-r--r--gas/testsuite/gas/arm/archv6t2.d51
-rw-r--r--gas/testsuite/gas/arm/archv6t2.s55
-rw-r--r--gas/testsuite/gas/arm/arm.exp2
8 files changed, 608 insertions, 2 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 6790664..ce3663d 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,13 @@
+2005-03-15 Zack Weinberg <zack@codesourcery.com>
+
+ * config/tc-arm.c (do_mla): Rename to do_mlas, take second
+ is_mls parameter; do not diagnose Rm==Rd when is_mls.
+ (do_mla, do_mls, five_bit_unsigned_immediate, bfci_lsb_and_width)
+ (do_bfc, do_bfi, do_bfx, do_rbit, do_mov16, do_ldsttv4): New functions.
+ (insns): Add ARMv6T2 instructions:
+ bfc bfi mls movw movt rbit sbfx ubfx ldrht ldrsht ldrsbt strht.
+ (arm_archs): Add V6T2 variants.
+
2005-03-15 Nick Clifton <nickc@redhat.com>
* NEWS: Add cutoff for changes in 2.16 release.
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 3ab5aa1..5cce0a9 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -2814,7 +2814,7 @@ do_mul (char * str)
}
static void
-do_mla (char * str)
+do_mlas (char * str, bfd_boolean is_mls)
{
int rd, rm;
@@ -2846,7 +2846,9 @@ do_mla (char * str)
return;
}
- if (rm == rd)
+ /* This restriction does not apply to mls (nor to mla in v6, but
+ that's hard to detect at present). */
+ if (rm == rd && !is_mls)
as_tsktsk (_("rd and rm should be different in mla"));
if (skip_past_comma (&str) == FAIL
@@ -2867,6 +2869,18 @@ do_mla (char * str)
end_of_line (str);
}
+static void
+do_mla (char *str)
+{
+ do_mlas (str, FALSE);
+}
+
+static void
+do_mls (char *str)
+{
+ do_mlas (str, TRUE);
+}
+
/* Expects *str -> the characters "acc0", possibly with leading blanks.
Advances *str to the next non-alphanumeric.
Returns 0, or else FAIL (in which case sets inst.error).
@@ -4512,6 +4526,286 @@ do_cpsi (char * str)
end_of_line (str);
}
+/* ARM V6T2 bitfield manipulation instructions. */
+
+static int
+five_bit_unsigned_immediate (char **str)
+{
+ expressionS expr;
+
+ skip_whitespace (*str);
+ if (!is_immediate_prefix (**str))
+ {
+ inst.error = _("immediate expression expected");
+ return -1;
+ }
+ (*str)++;
+ if (my_get_expression (&expr, str))
+ {
+ inst.error = _("bad expression");
+ return -1;
+ }
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return -1;
+ }
+ if (expr.X_add_number < 0 || expr.X_add_number > 32)
+ {
+ inst.error = _("immediate value out of range");
+ return -1;
+ }
+
+ return expr.X_add_number;
+}
+
+static void
+bfci_lsb_and_width (char *str)
+{
+ int lsb, width;
+
+ if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if ((width = five_bit_unsigned_immediate (&str)) == -1)
+ return;
+
+ end_of_line (str);
+
+ if (width == 0 || lsb == 32)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ else if (width + lsb > 32)
+ {
+ inst.error = _("bit-field extends past end of register");
+ return;
+ }
+
+ /* Convert to LSB/MSB and write to register. */
+ inst.instruction |= lsb << 7;
+ inst.instruction |= (width + lsb - 1) << 16;
+}
+
+static void
+do_bfc (char *str)
+{
+ int rd;
+
+ /* Rd. */
+ skip_whitespace (str);
+ if (((rd = reg_required_here (&str, 12)) == FAIL)
+ || (skip_past_comma (&str) == FAIL))
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ bfci_lsb_and_width (str);
+}
+
+static void
+do_bfi (char *str)
+{
+ int rd, rm;
+
+ /* Rd. */
+ skip_whitespace (str);
+ if (((rd = reg_required_here (&str, 12)) == FAIL)
+ || (skip_past_comma (&str) == FAIL))
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Rm. Accept #0 in this position as an alternative syntax for bfc. */
+ skip_whitespace (str);
+ if (is_immediate_prefix (*str))
+ {
+ expressionS expr;
+ str++;
+ if (my_get_expression (&expr, &str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+ if (expr.X_add_number != 0)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ inst.instruction |= 0x0000000f; /* Rm = PC -> bfc, not bfi. */
+ }
+ else
+ {
+ if ((rm = reg_required_here (&str, 0)) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rm == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+ }
+ if (skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ bfci_lsb_and_width (str);
+}
+
+static void
+do_bfx (char *str)
+{
+ int lsb, width;
+
+ /* Rd. */
+ skip_whitespace (str);
+ if (reg_required_here (&str, 12) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ /* Rm. */
+ skip_whitespace (str);
+ if (reg_required_here (&str, 0) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if ((lsb = five_bit_unsigned_immediate (&str)) == -1)
+ return;
+
+ if (skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ if ((width = five_bit_unsigned_immediate (&str)) == -1)
+ return;
+
+ end_of_line (str);
+
+ if (width == 0 || lsb == 32)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+ else if (width + lsb > 32)
+ {
+ inst.error = _("bit-field extends past end of register");
+ return;
+ }
+
+ inst.instruction |= lsb << 7;
+ inst.instruction |= (width - 1) << 16;
+}
+
+static void
+do_rbit (char *str)
+{
+ /* Rd. */
+ skip_whitespace (str);
+ if (reg_required_here (&str, 12) == FAIL
+ || skip_past_comma (&str) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ /* Rm. */
+ skip_whitespace (str);
+ if (reg_required_here (&str, 0) == FAIL)
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ end_of_line (str);
+}
+
+/* ARM V6T2 16-bit immediate register load: MOV[WT]{cond} Rd, #<imm16>. */
+static void
+do_mov16 (char *str)
+{
+ int rd;
+ expressionS expr;
+
+ /* Rd. */
+ skip_whitespace (str);
+ if (((rd = reg_required_here (&str, 12)) == FAIL)
+ || (skip_past_comma (&str) == FAIL))
+ {
+ inst.error = BAD_ARGS;
+ return;
+ }
+ else if (rd == REG_PC)
+ {
+ inst.error = BAD_PC;
+ return;
+ }
+
+ /* Imm16. */
+ skip_whitespace (str);
+ if (!is_immediate_prefix (*str))
+ {
+ inst.error = _("immediate expression expected");
+ return;
+ }
+ str++;
+ if (my_get_expression (&expr, &str))
+ {
+ inst.error = _("bad expression");
+ return;
+ }
+ if (expr.X_op != O_constant)
+ {
+ inst.error = _("constant expression expected");
+ return;
+ }
+ if (expr.X_add_number < 0 || expr.X_add_number > 65535)
+ {
+ inst.error = _("immediate value out of range");
+ return;
+ }
+
+ end_of_line (str);
+
+ /* The value is in two pieces: 0:11, 16:19. */
+ inst.instruction |= (expr.X_add_number & 0x00000fff);
+ inst.instruction |= (expr.X_add_number & 0x0000f000) << 4;
+}
+
+
/* THUMB V5 breakpoint instruction (argument parse)
BKPT <immed_8>. */
@@ -6517,6 +6811,84 @@ do_ldstv4 (char * str)
end_of_line (str);
}
+static void
+do_ldsttv4 (char * str)
+{
+ int conflict_reg;
+
+ skip_whitespace (str);
+
+ if ((conflict_reg = reg_required_here (& str, 12)) == FAIL)
+ {
+ if (!inst.error)
+ inst.error = BAD_ARGS;
+ return;
+ }
+
+ if (skip_past_comma (& str) == FAIL)
+ {
+ inst.error = _("address expected");
+ return;
+ }
+
+ if (*str == '[')
+ {
+ int reg;
+
+ str++;
+
+ skip_whitespace (str);
+
+ if ((reg = reg_required_here (&str, 16)) == FAIL)
+ return;
+
+ /* ldrt/strt always use post-indexed addressing, so if the base is
+ the same as Rd, we warn. */
+ if (conflict_reg == reg)
+ as_warn (_("%s register same as write-back base"),
+ ((inst.instruction & LOAD_BIT)
+ ? _("destination") : _("source")));
+
+ skip_whitespace (str);
+
+ if (*str == ']')
+ {
+ str ++;
+
+ if (skip_past_comma (&str) == SUCCESS)
+ {
+ /* [Rn],... (post inc) */
+ if (ldst_extend_v4 (&str) == FAIL)
+ return;
+ }
+ else
+ {
+ /* [Rn] */
+ skip_whitespace (str);
+
+ /* Skip a write-back '!'. */
+ if (*str == '!')
+ str++;
+
+ inst.instruction |= (INDEX_UP|HWOFFSET_IMM);
+ }
+ }
+ else
+ {
+ inst.error = _("post-indexed expression expected");
+ return;
+ }
+ }
+ else
+ {
+ inst.error = _("post-indexed expression expected");
+ return;
+ }
+
+ end_of_line (str);
+}
+
+
static long
reg_list (char ** strp)
{
@@ -10014,6 +10386,21 @@ static const struct asm_opcode insns[] =
/* ARM V6Z. */
{ "smi", 0xe1600070, 3, ARM_EXT_V6Z, do_smi},
+ /* ARM V6T2. */
+ { "bfc", 0xe7c0001f, 3, ARM_EXT_V6T2, do_bfc},
+ { "bfi", 0xe7c00010, 3, ARM_EXT_V6T2, do_bfi},
+ { "mls", 0xe0600090, 3, ARM_EXT_V6T2, do_mls},
+ { "movw", 0xe3000000, 4, ARM_EXT_V6T2, do_mov16},
+ { "movt", 0xe3400000, 4, ARM_EXT_V6T2, do_mov16},
+ { "rbit", 0xe3ff0f30, 4, ARM_EXT_V6T2, do_rbit},
+ { "sbfx", 0xe7a00050, 4, ARM_EXT_V6T2, do_bfx},
+ { "ubfx", 0xe7e00050, 4, ARM_EXT_V6T2, do_bfx},
+
+ { "ldrht", 0xe03000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
+ { "ldrsht", 0xe03000f0, 3, ARM_EXT_V6T2, do_ldsttv4},
+ { "ldrsbt", 0xe03000d0, 3, ARM_EXT_V6T2, do_ldsttv4},
+ { "strht", 0xe02000b0, 3, ARM_EXT_V6T2, do_ldsttv4},
+
/* Core FPA instruction set (V1). */
{"wfs", 0xee200110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
{"rfs", 0xee300110, 3, FPU_FPA_EXT_V1, do_fpa_ctrl},
@@ -12763,6 +13150,10 @@ static struct arm_arch_option_table arm_archs[] =
{"armv6k", ARM_ARCH_V6K, FPU_ARCH_VFP},
{"armv6z", ARM_ARCH_V6Z, FPU_ARCH_VFP},
{"armv6zk", ARM_ARCH_V6ZK, FPU_ARCH_VFP},
+ {"armv6t2", ARM_ARCH_V6T2, FPU_ARCH_VFP},
+ {"armv6kt2", ARM_ARCH_V6KT2, FPU_ARCH_VFP},
+ {"armv6zt2", ARM_ARCH_V6ZT2, FPU_ARCH_VFP},
+ {"armv6zkt2", ARM_ARCH_V6ZKT2, FPU_ARCH_VFP},
{"xscale", ARM_ARCH_XSCALE, FPU_ARCH_VFP},
{"iwmmxt", ARM_ARCH_IWMMXT, FPU_ARCH_VFP},
{NULL, 0, 0}
diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog
index 4ea866d..86af7eb 100644
--- a/gas/testsuite/ChangeLog
+++ b/gas/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2005-03-15 Zack Weinberg <zack@codesourcery.com>
+
+ * gas/arm/archv6t2.d, gas/arm/archv6t2.s: New dump test.
+ * gas/arm/archv6t2-bad.l, gas/arm/archv6t2-bad.l: New errors test.
+ * gas/arm/arm.exp: Run them.
+
2005-03-14 Eric Christopher <echristo@redhat.com>
* gas/cfi/cfi-mips-1.d, gas/cfi/cfi-mips-1.s: New dump test.
diff --git a/gas/testsuite/gas/arm/archv6t2-bad.l b/gas/testsuite/gas/arm/archv6t2-bad.l
new file mode 100644
index 0000000..e8da4b8
--- /dev/null
+++ b/gas/testsuite/gas/arm/archv6t2-bad.l
@@ -0,0 +1,38 @@
+[^:]*: Assembler messages:
+[^:]*:6: Error: r15 not allowed here -- `bfc pc,#0,#1'
+[^:]*:7: Error: r15 not allowed here -- `bfi pc,r0,#0,#1'
+[^:]*:8: Error: r15 not allowed here -- `movw pc,#0'
+[^:]*:9: Error: r15 not allowed here -- `movt pc,#0'
+[^:]*:12: Error: immediate value out of range -- `bfc r0,#0,#0'
+[^:]*:13: Error: immediate value out of range -- `bfc r0,#32,#0'
+[^:]*:14: Error: immediate value out of range -- `bfc r0,#0,#33'
+[^:]*:15: Error: immediate value out of range -- `bfc r0,#33,#1'
+[^:]*:16: Error: immediate value out of range -- `bfc r0,#32,#1'
+[^:]*:17: Error: bit-field extends past end of register -- `bfc r0,#28,#10'
+[^:]*:19: Error: immediate value out of range -- `bfi r0,r1,#0,#0'
+[^:]*:20: Error: immediate value out of range -- `bfi r0,r1,#32,#0'
+[^:]*:21: Error: immediate value out of range -- `bfi r0,r1,#0,#33'
+[^:]*:22: Error: immediate value out of range -- `bfi r0,r1,#33,#1'
+[^:]*:23: Error: immediate value out of range -- `bfi r0,r1,#32,#1'
+[^:]*:24: Error: bit-field extends past end of register -- `bfi r0,r1,#28,#10'
+[^:]*:26: Error: immediate value out of range -- `sbfx r0,r1,#0,#0'
+[^:]*:27: Error: immediate value out of range -- `sbfx r0,r1,#32,#0'
+[^:]*:28: Error: immediate value out of range -- `sbfx r0,r1,#0,#33'
+[^:]*:29: Error: immediate value out of range -- `sbfx r0,r1,#33,#1'
+[^:]*:30: Error: immediate value out of range -- `sbfx r0,r1,#32,#1'
+[^:]*:31: Error: bit-field extends past end of register -- `sbfx r0,r1,#28,#10'
+[^:]*:33: Error: immediate value out of range -- `ubfx r0,r1,#0,#0'
+[^:]*:34: Error: immediate value out of range -- `ubfx r0,r1,#32,#0'
+[^:]*:35: Error: immediate value out of range -- `ubfx r0,r1,#0,#33'
+[^:]*:36: Error: immediate value out of range -- `ubfx r0,r1,#33,#1'
+[^:]*:37: Error: immediate value out of range -- `ubfx r0,r1,#32,#1'
+[^:]*:38: Error: bit-field extends past end of register -- `ubfx r0,r1,#28,#10'
+[^:]*:41: Error: immediate value out of range -- `bfi r0,#1,#2,#3'
+[^:]*:44: Error: immediate value out of range -- `movt r0,#65537'
+[^:]*:45: Error: immediate value out of range -- `movw r0,#65537'
+[^:]*:46: Error: immediate value out of range -- `movt r0,#-1'
+[^:]*:47: Error: immediate value out of range -- `movw r0,#-1'
+[^:]*:50: Warning: destination register same as write-back base
+[^:]*:51: Warning: destination register same as write-back base
+[^:]*:52: Warning: destination register same as write-back base
+[^:]*:53: Warning: source register same as write-back base
diff --git a/gas/testsuite/gas/arm/archv6t2-bad.s b/gas/testsuite/gas/arm/archv6t2-bad.s
new file mode 100644
index 0000000..e568869
--- /dev/null
+++ b/gas/testsuite/gas/arm/archv6t2-bad.s
@@ -0,0 +1,53 @@
+ @ We do not bother testing simple cases, e.g. immediates where
+ @ registers belong, trailing junk at end of line.
+ .text
+x:
+ @ pc not allowed
+ bfc pc,#0,#1
+ bfi pc,r0,#0,#1
+ movw pc,#0
+ movt pc,#0
+
+ @ bitfield range limits
+ bfc r0,#0,#0
+ bfc r0,#32,#0
+ bfc r0,#0,#33
+ bfc r0,#33,#1
+ bfc r0,#32,#1
+ bfc r0,#28,#10
+
+ bfi r0,r1,#0,#0
+ bfi r0,r1,#32,#0
+ bfi r0,r1,#0,#33
+ bfi r0,r1,#33,#1
+ bfi r0,r1,#32,#1
+ bfi r0,r1,#28,#10
+
+ sbfx r0,r1,#0,#0
+ sbfx r0,r1,#32,#0
+ sbfx r0,r1,#0,#33
+ sbfx r0,r1,#33,#1
+ sbfx r0,r1,#32,#1
+ sbfx r0,r1,#28,#10
+
+ ubfx r0,r1,#0,#0
+ ubfx r0,r1,#32,#0
+ ubfx r0,r1,#0,#33
+ ubfx r0,r1,#33,#1
+ ubfx r0,r1,#32,#1
+ ubfx r0,r1,#28,#10
+
+ @ bfi accepts only #0 in Rm position
+ bfi r0,#1,#2,#3
+
+ @ mov16 range limits
+ movt r0,#65537
+ movw r0,#65537
+ movt r0,#-1
+ movw r0,#-1
+
+ @ ldsttv4 Rd == Rn (warning)
+ ldrht r0,[r0]
+ ldrsbt r0,[r0]
+ ldrsht r0,[r0]
+ strht r0,[r0]
diff --git a/gas/testsuite/gas/arm/archv6t2.d b/gas/testsuite/gas/arm/archv6t2.d
new file mode 100644
index 0000000..8e8b038
--- /dev/null
+++ b/gas/testsuite/gas/arm/archv6t2.d
@@ -0,0 +1,51 @@
+#name: ARM V6T2 instructions
+#as: -march=armv6t2
+#objdump: -dr --prefix-addresses --show-raw-insn
+
+.*: +file format .*arm.*
+
+Disassembly of section .text:
+0+00 <[^>]+> e7c00010 bfi r0, r0, #0, #1
+0+04 <[^>]+> 17c00010 bfine r0, r0, #0, #1
+0+08 <[^>]+> e7c09010 bfi r9, r0, #0, #1
+0+0c <[^>]+> e7c00019 bfi r0, r9, #0, #1
+0+10 <[^>]+> e7d10010 bfi r0, r0, #0, #18
+0+14 <[^>]+> e7d10890 bfi r0, r0, #17, #1
+0+18 <[^>]+> e7c0001f bfc r0, #0, #1
+0+1c <[^>]+> e7c0001f bfc r0, #0, #1
+0+20 <[^>]+> 17c0001f bfcne r0, #0, #1
+0+24 <[^>]+> e7c0901f bfc r9, #0, #1
+0+28 <[^>]+> e7d1001f bfc r0, #0, #18
+0+2c <[^>]+> e7d1089f bfc r0, #17, #1
+0+30 <[^>]+> e7a00050 sbfx r0, r0, #0, #1
+0+34 <[^>]+> 17a00050 sbfxne r0, r0, #0, #1
+0+38 <[^>]+> e7e00050 ubfx r0, r0, #0, #1
+0+3c <[^>]+> e7a09050 sbfx r9, r0, #0, #1
+0+40 <[^>]+> e7a00059 sbfx r0, r9, #0, #1
+0+44 <[^>]+> e7a008d0 sbfx r0, r0, #17, #1
+0+48 <[^>]+> e7b10050 sbfx r0, r0, #0, #18
+0+4c <[^>]+> e3ff0f30 rbit r0, r0
+0+50 <[^>]+> 13ff0f30 rbitne r0, r0
+0+54 <[^>]+> e3ff9f30 rbit r9, r0
+0+58 <[^>]+> e3ff0f39 rbit r0, r9
+0+5c <[^>]+> e0600090 mls r0, r0, r0, r0
+0+60 <[^>]+> 10600090 mlsne r0, r0, r0, r0
+0+64 <[^>]+> e0690090 mls r9, r0, r0, r0
+0+68 <[^>]+> e0600099 mls r0, r9, r0, r0
+0+6c <[^>]+> e0600990 mls r0, r0, r9, r0
+0+70 <[^>]+> e0609090 mls r0, r0, r0, r9
+0+74 <[^>]+> e3000000 movw r0, #0 ; 0x0
+0+78 <[^>]+> e3400000 movt r0, #0 ; 0x0
+0+7c <[^>]+> 13000000 movwne r0, #0 ; 0x0
+0+80 <[^>]+> e3009000 movw r9, #0 ; 0x0
+0+84 <[^>]+> e3000999 movw r0, #2457 ; 0x999
+0+88 <[^>]+> e3090000 movw r0, #36864 ; 0x9000
+0+8c <[^>]+> e0f900b0 ldrht r0, \[r9\]
+0+90 <[^>]+> e0f900f0 ldrsht r0, \[r9\]
+0+94 <[^>]+> e0f900d0 ldrsbt r0, \[r9\]
+0+98 <[^>]+> e0e900b0 strht r0, \[r9\]
+0+9c <[^>]+> 10f900b0 ldrneht r0, \[r9\]
+0+a0 <[^>]+> e0b090b9 ldrht r9, \[r0\], r9
+0+a4 <[^>]+> e03090b9 ldrht r9, \[r0\], -r9
+0+a8 <[^>]+> e0f099b9 ldrht r9, \[r0\], #153
+0+ac <[^>]+> e07099b9 ldrht r9, \[r0\], #-153
diff --git a/gas/testsuite/gas/arm/archv6t2.s b/gas/testsuite/gas/arm/archv6t2.s
new file mode 100644
index 0000000..292f11c
--- /dev/null
+++ b/gas/testsuite/gas/arm/archv6t2.s
@@ -0,0 +1,55 @@
+ .text
+x:
+ bfi r0, r0, #0, #1
+ bfine r0, r0, #0, #1
+
+ bfi r9, r0, #0, #1
+ bfi r0, r9, #0, #1
+ bfi r0, r0, #0, #18
+ bfi r0, r0, #17, #1
+
+ bfi r0, #0, #0, #1
+ bfc r0, #0, #1
+ bfcne r0, #0, #1
+ bfc r9, #0, #1
+ bfc r0, #0, #18
+ bfc r0, #17, #1
+
+ sbfx r0, r0, #0, #1
+ sbfxne r0, r0, #0, #1
+ ubfx r0, r0, #0, #1
+ sbfx r9, r0, #0, #1
+ sbfx r0, r9, #0, #1
+ sbfx r0, r0, #17, #1
+ sbfx r0, r0, #0, #18
+
+ rbit r0, r0
+ rbitne r0, r0
+ rbit r9, r0
+ rbit r0, r9
+
+ mls r0, r0, r0, r0
+ mlsne r0, r0, r0, r0
+ mls r9, r0, r0, r0
+ mls r0, r9, r0, r0
+ mls r0, r0, r9, r0
+ mls r0, r0, r0, r9
+
+ movw r0, #0
+ movt r0, #0
+ movwne r0, #0
+ movw r9, #0
+ movw r0, #0x0999
+ movw r0, #0x9000
+
+ @ for these, we must avoid write-back warnings
+ ldrht r0, [r9]
+ ldrsht r0, [r9]
+ ldrsbt r0, [r9]
+ strht r0, [r9]
+ ldrneht r0, [r9]
+
+ ldrht r9, [r0], r9
+ ldrht r9, [r0], -r9
+ ldrht r9, [r0], #0x99
+ ldrht r9, [r0], #-0x99
diff --git a/gas/testsuite/gas/arm/arm.exp b/gas/testsuite/gas/arm/arm.exp
index a84c80b..4ea6454 100644
--- a/gas/testsuite/gas/arm/arm.exp
+++ b/gas/testsuite/gas/arm/arm.exp
@@ -49,6 +49,7 @@ if {[istarget *arm*-*-*] || [istarget "xscale-*-*"]} then {
run_dump_test "reg-alias"
run_dump_test "maverick"
run_dump_test "archv6"
+ run_dump_test "archv6t2"
run_dump_test "thumbv6"
run_dump_test "thumbv6k"
run_dump_test "arch6zk"
@@ -57,6 +58,7 @@ if {[istarget *arm*-*-*] || [istarget "xscale-*-*"]} then {
run_errors_test "req" "-mcpu=arm7m" ".req errors"
run_errors_test "armv1-bad" "-mcpu=arm7m" "ARM v1 errors"
run_errors_test "r15-bad" "" "Invalid use of r15 errors"
+ run_errors_test "archv6t2-bad" "-march=armv6t2" "Invalid V6T2 instructions"
if {[istarget *-*-*coff] || [istarget *-*-pe] || [istarget *-*-wince] ||
[istarget *-*-*aout*] || [istarget *-*-netbsd] || [istarget *-*-riscix*]} then {