* 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.
This commit is contained in:
Zack Weinberg 2005-03-15 20:38:00 +00:00
parent 957d91c178
commit b05fe5cf68
8 changed files with 608 additions and 2 deletions

View File

@ -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.

View File

@ -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}

View File

@ -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.

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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

View File

@ -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 {