This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
Fix error message for badly composed ARM ldrex and strexinstructions
- From: Nick Clifton <nickc at redhat dot com>
- To: binutils at sourceware dot org
- Date: Thu, 10 Nov 2005 09:45:18 +0000
- Subject: Fix error message for badly composed ARM ldrex and strexinstructions
Hi Guys,
I am applying the attached patch to fix a problem with the ARM port
of gas assembling badly composed LDREX and STREX instructions -
under some circumstances it could produce a very confusing error
message.
Cheers
Nick
gas/ChangeLog
2005-11-10 Nick Clifton <nickc@redhat.com>
* config/tc-arm.c (BAD_ADDR_MODE): Define.
(arm_reg_parse_multi): Return NULL rather than FAIL.
(arm_reg_parse): Fix comment, the function returns FAIL rather
than NULL if it is unable to parse the register name.
(do_ldrex): Use BAD_ADDR_MODE.
Change error message for PC-relative addressing.
(do_strex): Likewise.
(do_t_ldrex): Use BAD_ADDR_MODE.
(do_t_strex): Likewise.
gas/testsuite/ChangeLog
2005-11-10 Nick Clifton <nickc@redhat.com>
* gas/arm/archv6t2-bad.s: Add tests of badly composed ldrex and
strex instructions.
* gas/arm/archv6t2-bad.l: Add expected error messages.
* gas/arm/r15-bad.l: Adjust error messages for r15 usage in ldrex
and strex instructions.
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.232
diff -c -3 -p -r1.232 tc-arm.c
*** gas/config/tc-arm.c 28 Oct 2005 00:50:03 -0000 1.232
--- gas/config/tc-arm.c 9 Nov 2005 18:25:52 -0000
*************** struct asm_opcode
*** 502,507 ****
--- 502,508 ----
#define BAD_OVERLAP _("registers may not be the same")
#define BAD_HIREG _("lo register required")
#define BAD_THUMB32 _("instruction not supported in Thumb16 mode")
+ #define BAD_ADDR_MODE _("instruction does not accept this addressing mode");
static struct hash_control *arm_ops_hsh;
static struct hash_control *arm_cond_hsh;
*************** arm_reg_parse_multi (char **ccp)
*** 843,849 ****
#ifdef REGISTER_PREFIX
if (*start != REGISTER_PREFIX)
! return FAIL;
start++;
#endif
#ifdef OPTIONAL_REGISTER_PREFIX
--- 844,850 ----
#ifdef REGISTER_PREFIX
if (*start != REGISTER_PREFIX)
! return NULL;
start++;
#endif
#ifdef OPTIONAL_REGISTER_PREFIX
*************** arm_reg_parse_multi (char **ccp)
*** 869,875 ****
}
/* As above, but the register must be of type TYPE, and the return
! value is the register number or NULL. */
static int
arm_reg_parse (char **ccp, enum arm_reg_type type)
--- 870,876 ----
}
/* As above, but the register must be of type TYPE, and the return
! value is the register number or FAIL. */
static int
arm_reg_parse (char **ccp, enum arm_reg_type type)
*************** parse_address (char **str, int i)
*** 3282,3287 ****
--- 3283,3290 ----
if (skip_past_char (&p, '[') == FAIL)
{
+ char * saved_p;
+
if (skip_past_char (&p, '=') == FAIL)
{
/* bare address - translate to PC-relative offset */
*************** parse_address (char **str, int i)
*** 3292,3297 ****
--- 3295,3302 ----
}
/* else a load-constant pseudo op, no special treatment needed here */
+ saved_p = p;
+
if (my_get_expression (&inst.reloc.exp, &p, GE_NO_PREFIX))
return FAIL;
*************** do_ldrex (void)
*** 4825,4834 ****
constraint (!inst.operands[1].isreg || !inst.operands[1].preind
|| inst.operands[1].postind || inst.operands[1].writeback
|| inst.operands[1].immisreg || inst.operands[1].shifted
! || inst.operands[1].negative,
! _("instruction does not accept this addressing mode"));
!
! constraint (inst.operands[1].reg == REG_PC, BAD_PC);
constraint (inst.reloc.exp.X_op != O_constant
|| inst.reloc.exp.X_add_number != 0,
--- 4830,4849 ----
constraint (!inst.operands[1].isreg || !inst.operands[1].preind
|| inst.operands[1].postind || inst.operands[1].writeback
|| inst.operands[1].immisreg || inst.operands[1].shifted
! || inst.operands[1].negative
! /* This can arise if the programmer has written
! strex rN, rM, foo
! or if they have mistakenly used a register name as the last
! operand, eg:
! strex rN, rM, rX
! It is very difficult to distinguish between these two cases
! because "rX" might actually be a label. ie the register
! name has been occluded by a symbol of the same name. So we
! just generate a general 'bad addressing mode' type error
! message and leave it up to the programmer to discover the
! true cause and fix their mistake. */
! || (inst.operands[1].reg == REG_PC),
! BAD_ADDR_MODE);
constraint (inst.reloc.exp.X_op != O_constant
|| inst.reloc.exp.X_add_number != 0,
*************** do_strex (void)
*** 5268,5277 ****
constraint (!inst.operands[2].isreg || !inst.operands[2].preind
|| inst.operands[2].postind || inst.operands[2].writeback
|| inst.operands[2].immisreg || inst.operands[2].shifted
! || inst.operands[2].negative,
! _("instruction does not accept this addressing mode"));
!
! constraint (inst.operands[2].reg == REG_PC, BAD_PC);
constraint (inst.operands[0].reg == inst.operands[1].reg
|| inst.operands[0].reg == inst.operands[2].reg, BAD_OVERLAP);
--- 5283,5292 ----
constraint (!inst.operands[2].isreg || !inst.operands[2].preind
|| inst.operands[2].postind || inst.operands[2].writeback
|| inst.operands[2].immisreg || inst.operands[2].shifted
! || inst.operands[2].negative
! /* See comment in do_ldrex(). */
! || (inst.operands[2].reg == REG_PC),
! BAD_ADDR_MODE);
constraint (inst.operands[0].reg == inst.operands[1].reg
|| inst.operands[0].reg == inst.operands[2].reg, BAD_OVERLAP);
*************** do_t_ldrex (void)
*** 6703,6709 ****
|| inst.operands[1].postind || inst.operands[1].writeback
|| inst.operands[1].immisreg || inst.operands[1].shifted
|| inst.operands[1].negative,
! _("instruction does not accept this addressing mode"));
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg << 16;
--- 6718,6724 ----
|| inst.operands[1].postind || inst.operands[1].writeback
|| inst.operands[1].immisreg || inst.operands[1].shifted
|| inst.operands[1].negative,
! BAD_ADDR_MODE);
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg << 16;
*************** do_t_strex (void)
*** 7578,7584 ****
|| inst.operands[2].postind || inst.operands[2].writeback
|| inst.operands[2].immisreg || inst.operands[2].shifted
|| inst.operands[2].negative,
! _("instruction does not accept this addressing mode"));
inst.instruction |= inst.operands[0].reg << 8;
inst.instruction |= inst.operands[1].reg << 12;
--- 7593,7599 ----
|| inst.operands[2].postind || inst.operands[2].writeback
|| inst.operands[2].immisreg || inst.operands[2].shifted
|| inst.operands[2].negative,
! BAD_ADDR_MODE);
inst.instruction |= inst.operands[0].reg << 8;
inst.instruction |= inst.operands[1].reg << 12;
Index: gas/testsuite/gas/arm/archv6t2-bad.l
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/archv6t2-bad.l,v
retrieving revision 1.1
diff -c -3 -p -r1.1 archv6t2-bad.l
*** gas/testsuite/gas/arm/archv6t2-bad.l 15 Mar 2005 20:38:00 -0000 1.1
--- gas/testsuite/gas/arm/archv6t2-bad.l 9 Nov 2005 18:25:52 -0000
***************
*** 36,38 ****
--- 36,40 ----
[^:]*: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
+ [^:]*:59: Error: instruction does not accept this addressing mode -- `ldrex r0,r2'
+ [^:]*:60: Error: instruction does not accept this addressing mode -- `strex r1,r0,r2'
Index: gas/testsuite/gas/arm/archv6t2-bad.s
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/archv6t2-bad.s,v
retrieving revision 1.1
diff -c -3 -p -r1.1 archv6t2-bad.s
*** gas/testsuite/gas/arm/archv6t2-bad.s 15 Mar 2005 20:38:00 -0000 1.1
--- gas/testsuite/gas/arm/archv6t2-bad.s 9 Nov 2005 18:25:52 -0000
*************** x:
*** 51,53 ****
--- 51,61 ----
ldrsbt r0,[r0]
ldrsht r0,[r0]
strht r0,[r0]
+
+ @ Bug reported by user. GAS used to issue an error message
+ @ "r15 not allowed here" for these two instructions because
+ @ it thought that the "r2" operand was a PC-relative branch
+ @ to a label called "r2".
+ ldrex r0, r2
+ strex r1, r0, r2
+
\ No newline at end of file
Index: gas/testsuite/gas/arm/r15-bad.l
===================================================================
RCS file: /cvs/src/src/gas/testsuite/gas/arm/r15-bad.l,v
retrieving revision 1.2
diff -c -3 -p -r1.2 r15-bad.l
*** gas/testsuite/gas/arm/r15-bad.l 18 May 2005 05:40:10 -0000 1.2
--- gas/testsuite/gas/arm/r15-bad.l 9 Nov 2005 18:25:52 -0000
***************
*** 30,36 ****
[^:]*:33: Error: r15 not allowed here -- `umaal r1,r2,r3,r15'
[^:]*:34: Error: r15 not allowed here -- `strex r15,r2,[[]r3[]]'
[^:]*:35: Error: r15 not allowed here -- `strex r1,r15,[[]r3[]]'
! [^:]*:36: Error: r15 not allowed here -- `strex r1,r2,[[]r15[]]'
[^:]*:37: Error: r15 not allowed here -- `ssat r15,#1,r2'
[^:]*:38: Error: r15 not allowed here -- `ssat r1,#1,r15'
[^:]*:39: Error: r15 not allowed here -- `ssat16 r15,#1,r2'
--- 30,36 ----
[^:]*:33: Error: r15 not allowed here -- `umaal r1,r2,r3,r15'
[^:]*:34: Error: r15 not allowed here -- `strex r15,r2,[[]r3[]]'
[^:]*:35: Error: r15 not allowed here -- `strex r1,r15,[[]r3[]]'
! [^:]*:36: Error: instruction does not accept this addressing mode -- `strex r1,r2,[[]r15[]]'
[^:]*:37: Error: r15 not allowed here -- `ssat r15,#1,r2'
[^:]*:38: Error: r15 not allowed here -- `ssat r1,#1,r15'
[^:]*:39: Error: r15 not allowed here -- `ssat16 r15,#1,r2'
***************
*** 58,64 ****
[^:]*:61: Error: r15 not allowed here -- `pkhtb r1,r15,r3'
[^:]*:62: Error: r15 not allowed here -- `pkhtb r1,r2,r15'
[^:]*:63: Error: r15 not allowed here -- `ldrex r15,[[]r2[]]'
! [^:]*:64: Error: r15 not allowed here -- `ldrex r1,[[]r15[]]'
[^:]*:65: Error: r15 not allowed here -- `swp r15,r2,[[]r3[]]'
[^:]*:66: Error: r15 not allowed here -- `swp r1,r15,[[]r3[]]'
[^:]*:67: Error: r15 not allowed here -- `swp r1,r2,[[]r15[]]'
--- 58,64 ----
[^:]*:61: Error: r15 not allowed here -- `pkhtb r1,r15,r3'
[^:]*:62: Error: r15 not allowed here -- `pkhtb r1,r2,r15'
[^:]*:63: Error: r15 not allowed here -- `ldrex r15,[[]r2[]]'
! [^:]*:64: Error: instruction does not accept this addressing mode -- `ldrex r1,[[]r15[]]'
[^:]*:65: Error: r15 not allowed here -- `swp r15,r2,[[]r3[]]'
[^:]*:66: Error: r15 not allowed here -- `swp r1,r15,[[]r3[]]'
[^:]*:67: Error: r15 not allowed here -- `swp r1,r2,[[]r15[]]'