From 01cfc07fb1258a3c0b51dd860ed24f8b9329be40 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 10 Nov 2005 09:41:14 +0000 Subject: [PATCH] * 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/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. --- gas/ChangeLog | 12 ++++++++++ gas/config/tc-arm.c | 35 ++++++++++++++++++---------- gas/testsuite/ChangeLog | 8 +++++++ gas/testsuite/gas/arm/archv6t2-bad.l | 2 ++ gas/testsuite/gas/arm/archv6t2-bad.s | 8 +++++++ gas/testsuite/gas/arm/r15-bad.l | 4 ++-- 6 files changed, 55 insertions(+), 14 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 0e3e69928b9..91039162e0a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2005-11-10 Nick Clifton + + * 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. + 2005-11-08 Jean-Jacques Metayer * config/tc-sparc.c (isoctal): Fix thinko. diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 9df9e0eb9ae..62ebd501d04 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -502,6 +502,7 @@ struct asm_opcode #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; @@ -843,7 +844,7 @@ arm_reg_parse_multi (char **ccp) #ifdef REGISTER_PREFIX if (*start != REGISTER_PREFIX) - return FAIL; + return NULL; start++; #endif #ifdef OPTIONAL_REGISTER_PREFIX @@ -869,7 +870,7 @@ arm_reg_parse_multi (char **ccp) } /* As above, but the register must be of type TYPE, and the return - value is the register number or NULL. */ + value is the register number or FAIL. */ static int arm_reg_parse (char **ccp, enum arm_reg_type type) @@ -4825,10 +4826,20 @@ do_ldrex (void) 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); + || 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, @@ -5268,10 +5279,10 @@ do_strex (void) 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); + || 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); @@ -6703,7 +6714,7 @@ do_t_ldrex (void) || 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")); + BAD_ADDR_MODE); inst.instruction |= inst.operands[0].reg << 12; inst.instruction |= inst.operands[1].reg << 16; @@ -7578,7 +7589,7 @@ do_t_strex (void) || 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")); + BAD_ADDR_MODE); inst.instruction |= inst.operands[0].reg << 8; inst.instruction |= inst.operands[1].reg << 12; diff --git a/gas/testsuite/ChangeLog b/gas/testsuite/ChangeLog index 5dfe8b655ca..d896190018c 100644 --- a/gas/testsuite/ChangeLog +++ b/gas/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2005-11-10 Nick Clifton + + * 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. + 2005-11-08 Arnold Metselaar * gas/all/cofftag.s: Convert numbers in .type diff --git a/gas/testsuite/gas/arm/archv6t2-bad.l b/gas/testsuite/gas/arm/archv6t2-bad.l index e8da4b8aad2..0f00db37b2b 100644 --- a/gas/testsuite/gas/arm/archv6t2-bad.l +++ b/gas/testsuite/gas/arm/archv6t2-bad.l @@ -36,3 +36,5 @@ [^:]*: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' diff --git a/gas/testsuite/gas/arm/archv6t2-bad.s b/gas/testsuite/gas/arm/archv6t2-bad.s index e56886912fb..af1397271b6 100644 --- a/gas/testsuite/gas/arm/archv6t2-bad.s +++ b/gas/testsuite/gas/arm/archv6t2-bad.s @@ -51,3 +51,11 @@ x: 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 diff --git a/gas/testsuite/gas/arm/r15-bad.l b/gas/testsuite/gas/arm/r15-bad.l index 02306360bc3..a172e9e9ef3 100644 --- a/gas/testsuite/gas/arm/r15-bad.l +++ b/gas/testsuite/gas/arm/r15-bad.l @@ -30,7 +30,7 @@ [^:]*: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[]]' +[^:]*: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,7 +58,7 @@ [^:]*: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[]]' +[^:]*: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[]]' -- 2.30.2