+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.
+
 2005-11-08   Jean-Jacques Metayer  <jean-jacques.metayer@thomson.net>
 
        * config/tc-sparc.c (isoctal): Fix thinko.
 
 #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;
 
 #ifdef REGISTER_PREFIX
   if (*start != REGISTER_PREFIX)
-    return FAIL;
+    return NULL;
   start++;
 #endif
 #ifdef OPTIONAL_REGISTER_PREFIX
 }
 
 /* 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)
   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,
   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);
              || 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;
              || 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;
 
 [^:]*: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'
 [^:]*: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[]]'