aboutsummaryrefslogtreecommitdiff
path: root/gas
diff options
context:
space:
mode:
authorDaniel Gutson <dgutson@codesourcery.com>2010-02-12 20:15:13 +0000
committerDaniel Gutson <dgutson@codesourcery.com>2010-02-12 20:15:13 +0000
commit5be8be5d5d9f0ff1ce3e319f0281e7d98103606b (patch)
treed9f1ab3128294dbb0eac8fa87fe626b1bdc9d174 /gas
parent081dfbf778bccf638e777fd4babc2911d0a59306 (diff)
downloadfsf-binutils-gdb-5be8be5d5d9f0ff1ce3e319f0281e7d98103606b.zip
fsf-binutils-gdb-5be8be5d5d9f0ff1ce3e319f0281e7d98103606b.tar.gz
fsf-binutils-gdb-5be8be5d5d9f0ff1ce3e319f0281e7d98103606b.tar.bz2
gas/
* config/tc-arm.c (asm_opcode): operands type change. (BAD_PC_ADDRESSING): New macro message. (BAD_PC_WRITEBACK): Likewise. (MIX_ARM_THUMB_OPERANDS): New macro. (operand_parse_code): Added enum values. (parse_operands): Added thumb/arm distinction, plus new enum values handling. (encode_arm_addr_mode_2): Validations enhanced. (encode_arm_addr_mode_3): Likewise. (do_rm_rd_rn): Likewise. (encode_thumb32_addr_mode): Likewise. (do_t_ldrex): Likewise. (do_t_ldst): Likewise. (do_t_strex): Likewise. (md_assemble): Call parse_operands with a new parameter. (OPS_1): New macro. (OPS_2): Likewise. (OPS_3): Likewise. (OPS_4): Likewise. (OPS_5): Likewise. (OPS_6): Likewise. (insns): Updated insns operands. gas/testsuite/ * gas/arm/sp-pc-validations-bad.d: New testcase. * gas/arm/sp-pc-validations-bad.l: New file. * gas/arm/sp-pc-validations-bad.s: New file. * gas/arm/sp-pc-validations-bad-t.d: New testcase. * gas/arm/sp-pc-validations-bad-t.l: New file. * gas/arm/sp-pc-validations-bad-t.s: New file. * gas/arm/sp-pc-usage-t.d: Removed invalid insns. * gas/arm/sp-pc-usage-t.s: Likewise. * gas/arm/unpredictable.d: Likewise. * gas/arm/unpredictable.s: Likewise. * gas/arm/thumb2_bcond.d: Added test. * gas/arm/thumb2_bcond.s: Likewise.
Diffstat (limited to 'gas')
-rw-r--r--gas/config/tc-arm.c184
-rw-r--r--gas/testsuite/gas/arm/sp-pc-usage-t.d117
-rw-r--r--gas/testsuite/gas/arm/sp-pc-usage-t.s5
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad-t.d2
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad-t.l243
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad-t.s367
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad.d2
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad.l172
-rw-r--r--gas/testsuite/gas/arm/sp-pc-validations-bad.s266
-rw-r--r--gas/testsuite/gas/arm/thumb2_bcond.d12
-rw-r--r--gas/testsuite/gas/arm/thumb2_bcond.s2
-rw-r--r--gas/testsuite/gas/arm/unpredictable.d4
-rw-r--r--gas/testsuite/gas/arm/unpredictable.s2
13 files changed, 1259 insertions, 119 deletions
diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c
index 2add801..4706600 100644
--- a/gas/config/tc-arm.c
+++ b/gas/config/tc-arm.c
@@ -559,7 +559,7 @@ struct asm_opcode
const char * template_name;
/* Parameters to instruction. */
- unsigned char operands[8];
+ unsigned int operands[8];
/* Conditional tag - see opcode_lookup. */
unsigned int tag : 4;
@@ -705,6 +705,10 @@ struct asm_opcode
#define BAD_IT_COND _("incorrect condition in IT block")
#define BAD_IT_IT _("IT falling in the range of a previous IT block")
#define MISSING_FNSTART _("missing .fnstart before unwinding directive")
+#define BAD_PC_ADDRESSING \
+ _("cannot use register index with PC-relative addressing")
+#define BAD_PC_WRITEBACK \
+ _("cannot use writeback with PC-relative addressing")
static struct hash_control * arm_ops_hsh;
static struct hash_control * arm_cond_hsh;
@@ -5729,6 +5733,11 @@ parse_neon_mov (char **str, int *which_operand)
return FAIL;
}
+/* Use this macro when the operand constraints are different
+ for ARM and THUMB (e.g. ldrd). */
+#define MIX_ARM_THUMB_OPERANDS(arm_operand, thumb_operand) \
+ ((arm_operand) | ((thumb_operand) << 16))
+
/* Matcher codes for parse_operands. */
enum operand_parse_code
{
@@ -5736,6 +5745,7 @@ enum operand_parse_code
OP_RR, /* ARM register */
OP_RRnpc, /* ARM register, not r15 */
+ OP_RRnpcsp, /* ARM register, neither r15 nor r13 (a.k.a. 'BadReg') */
OP_RRnpcb, /* ARM register, not r15, in square brackets */
OP_RRw, /* ARM register, not r15, optional trailing ! */
OP_RCP, /* Coprocessor number */
@@ -5835,6 +5845,7 @@ enum operand_parse_code
OP_oRR, /* ARM register */
OP_oRRnpc, /* ARM register, not the PC */
+ OP_oRRnpcsp, /* ARM register, neither the PC nor the SP (a.k.a. BadReg) */
OP_oRRw, /* ARM register, not r15, optional trailing ! */
OP_oRND, /* Optional Neon double precision register */
OP_oRNQ, /* Optional Neon quad precision register */
@@ -5846,6 +5857,11 @@ enum operand_parse_code
OP_oROR, /* ROR 0/8/16/24 */
OP_oBARRIER, /* Option argument for a barrier instruction. */
+ /* Some pre-defined mixed (ARM/THUMB) operands. */
+ OP_RR_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RR, OP_RRnpcsp),
+ OP_RRnpc_npcsp = MIX_ARM_THUMB_OPERANDS (OP_RRnpc, OP_RRnpcsp),
+ OP_oRRnpc_npcsp = MIX_ARM_THUMB_OPERANDS (OP_oRRnpc, OP_oRRnpcsp),
+
OP_FIRST_OPTIONAL = OP_oI7b
};
@@ -5854,14 +5870,15 @@ enum operand_parse_code
structure. Returns SUCCESS or FAIL depending on whether the
specified grammar matched. */
static int
-parse_operands (char *str, const unsigned char *pattern)
+parse_operands (char *str, const unsigned int *pattern, bfd_boolean thumb)
{
- unsigned const char *upat = pattern;
+ unsigned const int *upat = pattern;
char *backtrack_pos = 0;
const char *backtrack_error = 0;
int i, val, backtrack_index = 0;
enum arm_reg_type rtype;
parse_operand_result result;
+ unsigned int op_parse_code;
#define po_char_or_fail(chr) \
do \
@@ -5952,7 +5969,12 @@ parse_operands (char *str, const unsigned char *pattern)
for (i = 0; upat[i] != OP_stop; i++)
{
- if (upat[i] >= OP_FIRST_OPTIONAL)
+ op_parse_code = upat[i];
+ if (op_parse_code >= 1<<16)
+ op_parse_code = thumb ? (op_parse_code >> 16)
+ : (op_parse_code & ((1<<16)-1));
+
+ if (op_parse_code >= OP_FIRST_OPTIONAL)
{
/* Remember where we are in case we need to backtrack. */
gas_assert (!backtrack_pos);
@@ -5964,11 +5986,13 @@ parse_operands (char *str, const unsigned char *pattern)
if (i > 0 && (i > 1 || inst.operands[0].present))
po_char_or_fail (',');
- switch (upat[i])
+ switch (op_parse_code)
{
/* Registers */
case OP_oRRnpc:
+ case OP_oRRnpcsp:
case OP_RRnpc:
+ case OP_RRnpcsp:
case OP_oRR:
case OP_RR: po_reg_or_fail (REG_TYPE_RN); break;
case OP_RCP: po_reg_or_fail (REG_TYPE_CP); break;
@@ -6371,13 +6395,13 @@ parse_operands (char *str, const unsigned char *pattern)
break;
default:
- as_fatal (_("unhandled operand code %d"), upat[i]);
+ as_fatal (_("unhandled operand code %d"), op_parse_code);
}
/* Various value-based sanity checks and shared operations. We
do not signal immediate failures for the register constraints;
this allows a syntax error to take precedence. */
- switch (upat[i])
+ switch (op_parse_code)
{
case OP_oRRnpc:
case OP_RRnpc:
@@ -6389,6 +6413,17 @@ parse_operands (char *str, const unsigned char *pattern)
inst.error = BAD_PC;
break;
+ case OP_oRRnpcsp:
+ case OP_RRnpcsp:
+ if (inst.operands[i].isreg)
+ {
+ if (inst.operands[i].reg == REG_PC)
+ inst.error = BAD_PC;
+ else if (inst.operands[i].reg == REG_SP)
+ inst.error = BAD_SP;
+ }
+ break;
+
case OP_CPSF:
case OP_ENDI:
case OP_oROR:
@@ -6674,10 +6709,15 @@ encode_arm_addr_mode_common (int i, bfd_boolean is_t)
static void
encode_arm_addr_mode_2 (int i, bfd_boolean is_t)
{
+ const bfd_boolean is_pc = (inst.operands[i].reg == REG_PC);
+
encode_arm_addr_mode_common (i, is_t);
if (inst.operands[i].immisreg)
{
+ constraint ((inst.operands[i].imm == REG_PC
+ || (is_pc && inst.operands[i].writeback)),
+ BAD_PC_ADDRESSING);
inst.instruction |= INST_IMMEDIATE; /* yes, this is backwards */
inst.instruction |= inst.operands[i].imm;
if (!inst.operands[i].negative)
@@ -6695,6 +6735,16 @@ encode_arm_addr_mode_2 (int i, bfd_boolean is_t)
}
else /* immediate offset in inst.reloc */
{
+ if (is_pc && !inst.reloc.pc_rel)
+ {
+ const bfd_boolean is_load = ((inst.instruction & LOAD_BIT) != 0);
+ /* BAD_PC_ADDRESSING Condition =
+ is_load => is_t
+ which becomes !is_load || is_t. */
+ constraint ((!is_load || is_t),
+ BAD_PC_ADDRESSING);
+ }
+
if (inst.reloc.type == BFD_RELOC_UNUSED)
inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM;
}
@@ -6718,12 +6768,18 @@ encode_arm_addr_mode_3 (int i, bfd_boolean is_t)
if (inst.operands[i].immisreg)
{
+ constraint ((inst.operands[i].imm == REG_PC
+ || inst.operands[i].reg == REG_PC),
+ BAD_PC_ADDRESSING);
inst.instruction |= inst.operands[i].imm;
if (!inst.operands[i].negative)
inst.instruction |= INDEX_UP;
}
else /* immediate offset in inst.reloc */
{
+ constraint ((inst.operands[i].reg == REG_PC && !inst.reloc.pc_rel
+ && inst.operands[i].writeback),
+ BAD_PC_WRITEBACK);
inst.instruction |= HWOFFSET_IMM;
if (inst.reloc.type == BFD_RELOC_UNUSED)
inst.reloc.type = BFD_RELOC_ARM_OFFSET_IMM8;
@@ -6933,6 +6989,11 @@ do_rd_rn_rm (void)
static void
do_rm_rd_rn (void)
{
+ constraint ((inst.operands[2].reg == REG_PC), BAD_PC);
+ constraint (((inst.reloc.exp.X_op != O_constant
+ && inst.reloc.exp.X_op != O_illegal)
+ || inst.reloc.exp.X_add_number != 0),
+ BAD_ADDR_MODE);
inst.instruction |= inst.operands[0].reg;
inst.instruction |= inst.operands[1].reg << 12;
inst.instruction |= inst.operands[2].reg << 16;
@@ -7423,6 +7484,8 @@ do_ldrex (void)
|| inst.reloc.exp.X_add_number != 0,
_("offset must be zero in ARM encoding"));
+ constraint ((inst.operands[1].reg == REG_PC), BAD_PC);
+
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg << 16;
inst.reloc.type = BFD_RELOC_UNUSED;
@@ -8672,12 +8735,13 @@ encode_thumb32_shifted_operand (int i)
Thumb32 format load or store instruction. Reject forms that cannot
be used with such instructions. If is_t is true, reject forms that
cannot be used with a T instruction; if is_d is true, reject forms
- that cannot be used with a D instruction. */
+ that cannot be used with a D instruction. If it is a store insn,
+ reject PC in Rn. */
static void
encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
{
- bfd_boolean is_pc = (inst.operands[i].reg == REG_PC);
+ const bfd_boolean is_pc = (inst.operands[i].reg == REG_PC);
constraint (!inst.operands[i].isreg,
_("Instruction does not support =N addresses"));
@@ -8685,7 +8749,7 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
inst.instruction |= inst.operands[i].reg << 16;
if (inst.operands[i].immisreg)
{
- constraint (is_pc, _("cannot use register index with PC-relative addressing"));
+ constraint (is_pc, BAD_PC_ADDRESSING);
constraint (is_t || is_d, _("cannot use register index with this instruction"));
constraint (inst.operands[i].negative,
_("Thumb does not support negative register indexing"));
@@ -8710,10 +8774,11 @@ encode_thumb32_addr_mode (int i, bfd_boolean is_t, bfd_boolean is_d)
}
else if (inst.operands[i].preind)
{
- constraint (is_pc && inst.operands[i].writeback,
- _("cannot use writeback with PC-relative addressing"));
+ constraint (is_pc && inst.operands[i].writeback, BAD_PC_WRITEBACK);
constraint (is_t && inst.operands[i].writeback,
_("cannot use writeback with this instruction"));
+ constraint (is_pc && ((inst.instruction & THUMB2_LOAD_BIT) == 0)
+ && !inst.reloc.pc_rel, BAD_PC_ADDRESSING);
if (is_d)
{
@@ -9830,6 +9895,8 @@ do_t_ldrex (void)
|| inst.operands[1].negative,
BAD_ADDR_MODE);
+ constraint ((inst.operands[1].reg == REG_PC), BAD_PC);
+
inst.instruction |= inst.operands[0].reg << 12;
inst.instruction |= inst.operands[1].reg << 16;
inst.reloc.type = BFD_RELOC_ARM_T32_OFFSET_U8;
@@ -9889,6 +9956,8 @@ do_t_ldst (void)
/* [Rn, Rik] */
if (Rn <= 7 && inst.operands[1].imm <= 7)
goto op16;
+ else if (opcode != T_MNEM_ldr && opcode != T_MNEM_str)
+ reject_bad_reg (inst.operands[1].imm);
}
else if ((Rn <= 7 && opcode != T_MNEM_ldrsh
&& opcode != T_MNEM_ldrsb)
@@ -9928,6 +9997,12 @@ do_t_ldst (void)
}
}
/* Definitely a 32-bit variant. */
+
+ /* Do some validations regarding addressing modes. */
+ if (inst.operands[1].immisreg && opcode != T_MNEM_ldr
+ && opcode != T_MNEM_str)
+ reject_bad_reg (inst.operands[1].imm);
+
inst.instruction = THUMB_OP32 (opcode);
inst.instruction |= inst.operands[0].reg << 12;
encode_thumb32_addr_mode (1, /*is_t=*/FALSE, /*is_d=*/FALSE);
@@ -11177,6 +11252,8 @@ do_t_strex (void)
|| inst.operands[2].negative,
BAD_ADDR_MODE);
+ constraint (inst.operands[2].reg == REG_PC, BAD_PC);
+
inst.instruction |= inst.operands[0].reg << 8;
inst.instruction |= inst.operands[1].reg << 12;
inst.instruction |= inst.operands[2].reg << 16;
@@ -15653,7 +15730,7 @@ md_assemble (char *str)
inst.instruction = opcode->tvalue;
- if (!parse_operands (p, opcode->operands))
+ if (!parse_operands (p, opcode->operands, /*thumb=*/TRUE))
{
/* Prepare the it_insn_type for those encodings that don't set
it. */
@@ -15726,7 +15803,7 @@ md_assemble (char *str)
else
inst.instruction |= inst.cond << 28;
inst.size = INSN_SIZE;
- if (!parse_operands (p, opcode->operands))
+ if (!parse_operands (p, opcode->operands, /*thumb=*/FALSE))
{
it_fsm_pre_encode ();
opcode->aencode ();
@@ -16150,6 +16227,18 @@ static struct asm_barrier_opt barrier_opt_names[] =
#define OPS5(a,b,c,d,e) { OP_##a,OP_##b,OP_##c,OP_##d,OP_##e, }
#define OPS6(a,b,c,d,e,f) { OP_##a,OP_##b,OP_##c,OP_##d,OP_##e,OP_##f, }
+/* These macros are similar to the OPSn, but do not prepend the OP_ prefix.
+ This is useful when mixing operands for ARM and THUMB, i.e. using the
+ MIX_ARM_THUMB_OPERANDS macro.
+ In order to use these macros, prefix the number of operands with _
+ e.g. _3. */
+#define OPS_1(a) { a, }
+#define OPS_2(a,b) { a,b, }
+#define OPS_3(a,b,c) { a,b,c, }
+#define OPS_4(a,b,c,d) { a,b,c,d, }
+#define OPS_5(a,b,c,d,e) { a,b,c,d,e, }
+#define OPS_6(a,b,c,d,e,f) { a,b,c,d,e,f, }
+
/* These macros abstract out the exact format of the mnemonic table and
save some repeated characters. */
@@ -16370,9 +16459,11 @@ static const struct asm_opcode insns[] =
tC3("mvns", 1f00000, _mvns, 2, (RR, SH), mov, t_mvn_tst),
tCE("ldr", 4100000, _ldr, 2, (RR, ADDRGLDR),ldst, t_ldst),
- tC3("ldrb", 4500000, _ldrb, 2, (RR, ADDRGLDR),ldst, t_ldst),
- tCE("str", 4000000, _str, 2, (RR, ADDRGLDR),ldst, t_ldst),
- tC3("strb", 4400000, _strb, 2, (RR, ADDRGLDR),ldst, t_ldst),
+ tC3("ldrb", 4500000, _ldrb, 2, (RRnpc_npcsp, ADDRGLDR),ldst, t_ldst),
+ tCE("str", 4000000, _str, _2, (MIX_ARM_THUMB_OPERANDS (OP_RR,
+ OP_RRnpc),
+ OP_ADDRGLDR),ldst, t_ldst),
+ tC3("strb", 4400000, _strb, 2, (RRnpc_npcsp, ADDRGLDR),ldst, t_ldst),
tCE("stm", 8800000, _stmia, 2, (RRw, REGLST), ldmstm, t_ldmstm),
tC3("stmia", 8800000, _stmia, 2, (RRw, REGLST), ldmstm, t_ldmstm),
@@ -16422,10 +16513,10 @@ static const struct asm_opcode insns[] =
TC3w("teqs", 1300000, ea900f00, 2, (RR, SH), cmp, t_mvn_tst),
CL("teqp", 130f000, 2, (RR, SH), cmp),
- TC3("ldrt", 4300000, f8500e00, 2, (RR, ADDR), ldstt, t_ldstt),
- TC3("ldrbt", 4700000, f8100e00, 2, (RR, ADDR), ldstt, t_ldstt),
- TC3("strt", 4200000, f8400e00, 2, (RR, ADDR), ldstt, t_ldstt),
- TC3("strbt", 4600000, f8000e00, 2, (RR, ADDR), ldstt, t_ldstt),
+ TC3("ldrt", 4300000, f8500e00, 2, (RRnpc_npcsp, ADDR),ldstt, t_ldstt),
+ TC3("ldrbt", 4700000, f8100e00, 2, (RRnpc_npcsp, ADDR),ldstt, t_ldstt),
+ TC3("strt", 4200000, f8400e00, 2, (RR_npcsp, ADDR), ldstt, t_ldstt),
+ TC3("strbt", 4600000, f8000e00, 2, (RRnpc_npcsp, ADDR),ldstt, t_ldstt),
TC3("stmdb", 9000000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
TC3("stmfd", 9000000, e9000000, 2, (RRw, REGLST), ldmstm, t_ldmstm),
@@ -16502,12 +16593,12 @@ static const struct asm_opcode insns[] =
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_v4t
- tC3("ldrh", 01000b0, _ldrh, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
- tC3("strh", 00000b0, _strh, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
- tC3("ldrsh", 01000f0, _ldrsh, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
- tC3("ldrsb", 01000d0, _ldrsb, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
- tCM("ld","sh", 01000f0, _ldrsh, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
- tCM("ld","sb", 01000d0, _ldrsb, 2, (RR, ADDRGLDRS), ldstv4, t_ldst),
+ tC3("ldrh", 01000b0, _ldrh, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
+ tC3("strh", 00000b0, _strh, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
+ tC3("ldrsh", 01000f0, _ldrsh, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
+ tC3("ldrsb", 01000d0, _ldrsb, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
+ tCM("ld","sh", 01000f0, _ldrsh, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
+ tCM("ld","sb", 01000d0, _ldrsb, 2, (RRnpc_npcsp, ADDRGLDRS), ldstv4, t_ldst),
#undef ARM_VARIANT
#define ARM_VARIANT & arm_ext_v4t_5
@@ -16576,8 +16667,10 @@ static const struct asm_opcode insns[] =
#define THUMB_VARIANT &arm_ext_v6t2
TUF("pld", 450f000, f810f000, 1, (ADDR), pld, t_pld),
- TC3("ldrd", 00000d0, e8500000, 3, (RRnpc, oRRnpc, ADDRGLDRS), ldrd, t_ldstd),
- TC3("strd", 00000f0, e8400000, 3, (RRnpc, oRRnpc, ADDRGLDRS), ldrd, t_ldstd),
+ TC3("ldrd", 00000d0, e8500000, 3, (RRnpc_npcsp, oRRnpc_npcsp, ADDRGLDRS),
+ ldrd, t_ldstd),
+ TC3("strd", 00000f0, e8400000, 3, (RRnpc_npcsp, oRRnpc_npcsp,
+ ADDRGLDRS), ldrd, t_ldstd),
TCE("mcrr", c400000, ec400000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
TCE("mrrc", c500000, ec500000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
@@ -16606,8 +16699,9 @@ static const struct asm_opcode insns[] =
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_v6t2
- TCE("ldrex", 1900f9f, e8500f00, 2, (RRnpc, ADDR), ldrex, t_ldrex),
- TCE("strex", 1800f90, e8400000, 3, (RRnpc, RRnpc, ADDR), strex, t_strex),
+ TCE("ldrex", 1900f9f, e8500f00, 2, (RRnpc_npcsp, ADDR), ldrex, t_ldrex),
+ TCE("strex", 1800f90, e8400000, 3, (RRnpc_npcsp, RRnpc_npcsp, ADDR),
+ strex, t_strex),
TUF("mcrr2", c400000, fc400000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
TUF("mrrc2", c500000, fc500000, 5, (RCP, I15b, RRnpc, RRnpc, RCN), co_reg2c, co_reg2c),
@@ -16741,17 +16835,21 @@ static const struct asm_opcode insns[] =
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_v6_notm
-
- TCE("ldrexd", 1b00f9f, e8d0007f, 3, (RRnpc, oRRnpc, RRnpcb), ldrexd, t_ldrexd),
- TCE("strexd", 1a00f90, e8c00070, 4, (RRnpc, RRnpc, oRRnpc, RRnpcb), strexd, t_strexd),
+ TCE("ldrexd", 1b00f9f, e8d0007f, 3, (RRnpc_npcsp, oRRnpc_npcsp, RRnpcb),
+ ldrexd, t_ldrexd),
+ TCE("strexd", 1a00f90, e8c00070, 4, (RRnpc_npcsp, RRnpc_npcsp, oRRnpc_npcsp,
+ RRnpcb), strexd, t_strexd),
#undef THUMB_VARIANT
#define THUMB_VARIANT & arm_ext_v6t2
-
- TCE("ldrexb", 1d00f9f, e8d00f4f, 2, (RRnpc, RRnpcb), rd_rn, rd_rn),
- TCE("ldrexh", 1f00f9f, e8d00f5f, 2, (RRnpc, RRnpcb), rd_rn, rd_rn),
- TCE("strexb", 1c00f90, e8c00f40, 3, (RRnpc, RRnpc, ADDR), strex, rm_rd_rn),
- TCE("strexh", 1e00f90, e8c00f50, 3, (RRnpc, RRnpc, ADDR), strex, rm_rd_rn),
+ TCE("ldrexb", 1d00f9f, e8d00f4f, 2, (RRnpc_npcsp,RRnpcb),
+ rd_rn, rd_rn),
+ TCE("ldrexh", 1f00f9f, e8d00f5f, 2, (RRnpc_npcsp, RRnpcb),
+ rd_rn, rd_rn),
+ TCE("strexb", 1c00f90, e8c00f40, 3, (RRnpc_npcsp, RRnpc_npcsp, ADDR),
+ strex, rm_rd_rn),
+ TCE("strexh", 1e00f90, e8c00f50, 3, (RRnpc_npcsp, RRnpc_npcsp, ADDR),
+ strex, rm_rd_rn),
TUF("clrex", 57ff01f, f3bf8f2f, 0, (), noargs, noargs),
#undef ARM_VARIANT
@@ -16772,10 +16870,10 @@ static const struct asm_opcode insns[] =
TCE("movt", 3400000, f2c00000, 2, (RRnpc, HALF), mov16, t_mov16),
TCE("rbit", 6ff0f30, fa90f0a0, 2, (RR, RR), rd_rm, t_rbit),
- TC3("ldrht", 03000b0, f8300e00, 2, (RR, ADDR), ldsttv4, t_ldstt),
- TC3("ldrsht", 03000f0, f9300e00, 2, (RR, ADDR), ldsttv4, t_ldstt),
- TC3("ldrsbt", 03000d0, f9100e00, 2, (RR, ADDR), ldsttv4, t_ldstt),
- TC3("strht", 02000b0, f8200e00, 2, (RR, ADDR), ldsttv4, t_ldstt),
+ TC3("ldrht", 03000b0, f8300e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt),
+ TC3("ldrsht", 03000f0, f9300e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt),
+ TC3("ldrsbt", 03000d0, f9100e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt),
+ TC3("strht", 02000b0, f8200e00, 2, (RRnpc_npcsp, ADDR), ldsttv4, t_ldstt),
UT("cbnz", b900, 2, (RR, EXP), t_cbz),
UT("cbz", b100, 2, (RR, EXP), t_cbz),
diff --git a/gas/testsuite/gas/arm/sp-pc-usage-t.d b/gas/testsuite/gas/arm/sp-pc-usage-t.d
index 8b21aeb..706f2a1 100644
--- a/gas/testsuite/gas/arm/sp-pc-usage-t.d
+++ b/gas/testsuite/gas/arm/sp-pc-usage-t.d
@@ -24,65 +24,60 @@ Disassembly of section .text:
00000036 <foo\+0x36> f8df d000 ldr.w sp, \[pc\] ; 00000038 <foo\+0x38>
0000003a <foo\+0x3a> f850 d00f ldr.w sp, \[r0, pc\]
0000003e <foo\+0x3e> 9000 str r0, \[sp, #0\]
-00000040 <foo\+0x40> f8cf 0000 str.w r0, \[pc\] ; 00000044 <foo\+0x44>
-00000044 <foo\+0x44> f8c0 f000 str.w pc, \[r0\]
-00000048 <foo\+0x48> f8c0 d000 str.w sp, \[r0\]
-0000004c <foo\+0x4c> f8cf f000 str.w pc, \[pc\] ; 00000050 <foo\+0x50>
-00000050 <foo\+0x50> f8cd d000 str.w sp, \[sp\]
-00000054 <foo\+0x54> f8cd f000 str.w pc, \[sp\]
-00000058 <foo\+0x58> f8cf d000 str.w sp, \[pc\] ; 0000005c <foo\+0x5c>
-0000005c <foo\+0x5c> f840 d00f str.w sp, \[r0, pc\]
-00000060 <foo\+0x60> 4468 add r0, sp
-00000062 <foo\+0x62> eb1d 0000 adds.w r0, sp, r0
-00000066 <foo\+0x66> eb0d 0040 add.w r0, sp, r0, lsl #1
-0000006a <foo\+0x6a> eb1d 0040 adds.w r0, sp, r0, lsl #1
-0000006e <foo\+0x6e> f11d 0f00 cmn.w sp, #0
-00000072 <foo\+0x72> eb1d 0f00 cmn.w sp, r0
-00000076 <foo\+0x76> eb1d 0f40 cmn.w sp, r0, lsl #1
-0000007a <foo\+0x7a> f1bd 0f00 cmp.w sp, #0
-0000007e <foo\+0x7e> 4585 cmp sp, r0
-00000080 <foo\+0x80> ebbd 0f40 cmp.w sp, r0, lsl #1
-00000084 <foo\+0x84> b080 sub sp, #0
-00000086 <foo\+0x86> f1bd 0d00 subs.w sp, sp, #0
-0000008a <foo\+0x8a> f1ad 0000 sub.w r0, sp, #0
-0000008e <foo\+0x8e> f1bd 0000 subs.w r0, sp, #0
-00000092 <foo\+0x92> b001 add sp, #4
-00000094 <foo\+0x94> a801 add r0, sp, #4
-00000096 <foo\+0x96> f11d 0d04 adds.w sp, sp, #4
-0000009a <foo\+0x9a> f11d 0004 adds.w r0, sp, #4
-0000009e <foo\+0x9e> f20d 0004 addw r0, sp, #4
-000000a2 <foo\+0xa2> b001 add sp, #4
-000000a4 <foo\+0xa4> f11d 0d04 adds.w sp, sp, #4
-000000a8 <foo\+0xa8> f20d 0d04 addw sp, sp, #4
+00000040 <foo\+0x40> f8c0 d000 str.w sp, \[r0\]
+00000044 <foo\+0x44> f8cd d000 str.w sp, \[sp\]
+00000048 <foo\+0x48> f840 d00f str.w sp, \[r0, pc\]
+0000004c <foo\+0x4c> 4468 add r0, sp
+0000004e <foo\+0x4e> eb1d 0000 adds.w r0, sp, r0
+00000052 <foo\+0x52> eb0d 0040 add.w r0, sp, r0, lsl #1
+00000056 <foo\+0x56> eb1d 0040 adds.w r0, sp, r0, lsl #1
+0000005a <foo\+0x5a> f11d 0f00 cmn.w sp, #0
+0000005e <foo\+0x5e> eb1d 0f00 cmn.w sp, r0
+00000062 <foo\+0x62> eb1d 0f40 cmn.w sp, r0, lsl #1
+00000066 <foo\+0x66> f1bd 0f00 cmp.w sp, #0
+0000006a <foo\+0x6a> 4585 cmp sp, r0
+0000006c <foo\+0x6c> ebbd 0f40 cmp.w sp, r0, lsl #1
+00000070 <foo\+0x70> b080 sub sp, #0
+00000072 <foo\+0x72> f1bd 0d00 subs.w sp, sp, #0
+00000076 <foo\+0x76> f1ad 0000 sub.w r0, sp, #0
+0000007a <foo\+0x7a> f1bd 0000 subs.w r0, sp, #0
+0000007e <foo\+0x7e> b001 add sp, #4
+00000080 <foo\+0x80> a801 add r0, sp, #4
+00000082 <foo\+0x82> f11d 0d04 adds.w sp, sp, #4
+00000086 <foo\+0x86> f11d 0004 adds.w r0, sp, #4
+0000008a <foo\+0x8a> f20d 0004 addw r0, sp, #4
+0000008e <foo\+0x8e> b001 add sp, #4
+00000090 <foo\+0x90> f11d 0d04 adds.w sp, sp, #4
+00000094 <foo\+0x94> f20d 0d04 addw sp, sp, #4
+00000098 <foo\+0x98> 4485 add sp, r0
+0000009a <foo\+0x9a> 4468 add r0, sp
+0000009c <foo\+0x9c> eb0d 0040 add.w r0, sp, r0, lsl #1
+000000a0 <foo\+0xa0> eb1d 0d00 adds.w sp, sp, r0
+000000a4 <foo\+0xa4> eb1d 0000 adds.w r0, sp, r0
+000000a8 <foo\+0xa8> eb1d 0040 adds.w r0, sp, r0, lsl #1
000000ac <foo\+0xac> 4485 add sp, r0
-000000ae <foo\+0xae> 4468 add r0, sp
-000000b0 <foo\+0xb0> eb0d 0040 add.w r0, sp, r0, lsl #1
-000000b4 <foo\+0xb4> eb1d 0d00 adds.w sp, sp, r0
-000000b8 <foo\+0xb8> eb1d 0000 adds.w r0, sp, r0
-000000bc <foo\+0xbc> eb1d 0040 adds.w r0, sp, r0, lsl #1
-000000c0 <foo\+0xc0> 4485 add sp, r0
-000000c2 <foo\+0xc2> eb0d 0d40 add.w sp, sp, r0, lsl #1
-000000c6 <foo\+0xc6> eb1d 0d00 adds.w sp, sp, r0
-000000ca <foo\+0xca> eb1d 0d40 adds.w sp, sp, r0, lsl #1
-000000ce <foo\+0xce> 44ed add sp, sp
-000000d0 <foo\+0xd0> f1ad 0000 sub.w r0, sp, #0
-000000d4 <foo\+0xd4> f1bd 0000 subs.w r0, sp, #0
-000000d8 <foo\+0xd8> f2ad 0000 subw r0, sp, #0
-000000dc <foo\+0xdc> b080 sub sp, #0
-000000de <foo\+0xde> f1bd 0d00 subs.w sp, sp, #0
-000000e2 <foo\+0xe2> f2ad 0d00 subw sp, sp, #0
-000000e6 <foo\+0xe6> b080 sub sp, #0
-000000e8 <foo\+0xe8> f1bd 0d00 subs.w sp, sp, #0
-000000ec <foo\+0xec> ebad 0040 sub.w r0, sp, r0, lsl #1
-000000f0 <foo\+0xf0> ebbd 0040 subs.w r0, sp, r0, lsl #1
-000000f4 <foo\+0xf4> ebad 0d40 sub.w sp, sp, r0, lsl #1
-000000f8 <foo\+0xf8> ebbd 0d40 subs.w sp, sp, r0, lsl #1
-000000fc <foo\+0xfc> a001 add r0, pc, #4 ; \(adr r0, 00000104 <foo\+0x104>\)
-000000fe <foo\+0xfe> f2af 0004 subw r0, pc, #4
-00000102 <foo\+0x102> f20f 0004 addw r0, pc, #4
-00000106 <foo\+0x106> f2af 0004 subw r0, pc, #4
-0000010a <foo\+0x10a> f20f 0004 addw r0, pc, #4
-0000010e <foo\+0x10e> f2af 0004 subw r0, pc, #4
-00000112 <foo\+0x112> bf00[ ]+nop
-00000114 <foo\+0x114> bf00[ ]+nop
-00000116 <foo\+0x116> bf00[ ]+nop
+000000ae <foo\+0xae> eb0d 0d40 add.w sp, sp, r0, lsl #1
+000000b2 <foo\+0xb2> eb1d 0d00 adds.w sp, sp, r0
+000000b6 <foo\+0xb6> eb1d 0d40 adds.w sp, sp, r0, lsl #1
+000000ba <foo\+0xba> 44ed add sp, sp
+000000bc <foo\+0xbc> f1ad 0000 sub.w r0, sp, #0
+000000c0 <foo\+0xc0> f1bd 0000 subs.w r0, sp, #0
+000000c4 <foo\+0xc4> f2ad 0000 subw r0, sp, #0
+000000c8 <foo\+0xc8> b080 sub sp, #0
+000000ca <foo\+0xca> f1bd 0d00 subs.w sp, sp, #0
+000000ce <foo\+0xce> f2ad 0d00 subw sp, sp, #0
+000000d2 <foo\+0xd2> b080 sub sp, #0
+000000d4 <foo\+0xd4> f1bd 0d00 subs.w sp, sp, #0
+000000d8 <foo\+0xd8> ebad 0040 sub.w r0, sp, r0, lsl #1
+000000dc <foo\+0xdc> ebbd 0040 subs.w r0, sp, r0, lsl #1
+000000e0 <foo\+0xe0> ebad 0d40 sub.w sp, sp, r0, lsl #1
+000000e4 <foo\+0xe4> ebbd 0d40 subs.w sp, sp, r0, lsl #1
+000000e8 <foo\+0xe8> a001 add r0, pc, #4 ; \(adr r0, 000000f0 <foo\+0xf0>\)
+000000ea <foo\+0xea> f2af 0004 subw r0, pc, #4
+000000ee <foo\+0xee> f20f 0004 addw r0, pc, #4
+000000f2 <foo\+0xf2> f2af 0004 subw r0, pc, #4
+000000f6 <foo\+0xf6> f20f 0004 addw r0, pc, #4
+000000fa <foo\+0xfa> f2af 0004 subw r0, pc, #4
+000000fe <foo\+0xfe> bf00[ ]+nop
+00000100 <foo\+0x100> bf00[ ]+nop
+00000102 <foo\+0x102> bf00[ ]+nop
diff --git a/gas/testsuite/gas/arm/sp-pc-usage-t.s b/gas/testsuite/gas/arm/sp-pc-usage-t.s
index cf38594..1756866 100644
--- a/gas/testsuite/gas/arm/sp-pc-usage-t.s
+++ b/gas/testsuite/gas/arm/sp-pc-usage-t.s
@@ -38,13 +38,8 @@ ldr sp, [pc]
ldr sp, [r0, +pc]
str r0, [sp]
-str r0, [pc]
-str pc, [r0]
str sp, [r0]
-str pc, [pc]
str sp, [sp]
-str pc, [sp]
-str sp, [pc]
str sp, [r0, +pc]
@ R13 as the first operand <Rn> in any add{s}, cmn, cmp, or sub{s} instruction.
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad-t.d b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.d
new file mode 100644
index 0000000..8579f43
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.d
@@ -0,0 +1,2 @@
+# name: Invalid SP and PC operands test - THUMB
+# error-output: sp-pc-validations-bad-t.l
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad-t.l b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.l
new file mode 100644
index 0000000..120f6f3
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.l
@@ -0,0 +1,243 @@
+[^:]*: Assembler messages:
+[^:]*:27: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0\]'
+[^:]*:28: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0,#0\]'
+[^:]*:29: Error: branch must be last instruction in IT block -- `ldreq r15,\[sp\]'
+[^:]*:30: Error: branch must be last instruction in IT block -- `ldreq r15,\[sp,#0\]'
+[^:]*:31: Error: branch must be last instruction in IT block -- `ldreq.w r15,\[r0\]'
+[^:]*:32: Error: branch must be last instruction in IT block -- `ldreq.w r15,\[r0,#0\]'
+[^:]*:33: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0,#-4\]'
+[^:]*:34: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0\],#4'
+[^:]*:35: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0,#0\]!'
+[^:]*:38: Error: branch must be last instruction in IT block -- `ldreq r15,label'
+[^:]*:39: Error: branch must be last instruction in IT block -- `ldreq.w r15,label'
+[^:]*:40: Error: branch must be last instruction in IT block -- `ldreq.w r15,\[pc,#-0\]'
+[^:]*:43: Error: branch must be last instruction in IT block -- `ldreq r15,\[r0,r1\]'
+[^:]*:44: Error: branch must be last instruction in IT block -- `ldreq.w r15,\[r0,r1\]'
+[^:]*:45: Error: branch must be last instruction in IT block -- `ldreq.w r15,\[r0,r1,LSL#2\]'
+[^:]*:48: Error: r15 not allowed here -- `ldrb pc,\[r0,#4\]'
+[^:]*:50: Error: r13 not allowed here -- `ldrb.w sp,\[r0,#4\]'
+[^:]*:51: Error: r15 not allowed here -- `ldrb.w pc,\[r0,#4\]'
+[^:]*:52: Error: r15 not allowed here -- `ldrb pc,\[r0,#-4\]'
+[^:]*:54: Error: r15 not allowed here -- `ldrb pc,\[r0\],#4'
+[^:]*:55: Error: r13 not allowed here -- `ldrb sp,\[r0\],#4'
+[^:]*:56: Error: r15 not allowed here -- `ldrb pc,\[r0,#4\]!'
+[^:]*:57: Error: r13 not allowed here -- `ldrb sp,\[r0,#4\]!'
+[^:]*:60: Error: r15 not allowed here -- `ldrb pc,label'
+[^:]*:61: Error: r15 not allowed here -- `ldrb pc,\[PC,#-0\]'
+[^:]*:62: Error: r13 not allowed here -- `ldrb sp,label'
+[^:]*:63: Error: r13 not allowed here -- `ldrb sp,\[PC,#-0\]'
+[^:]*:66: Error: r15 not allowed here -- `ldrb pc,\[r0,r1\]'
+[^:]*:67: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[pc,r1\]'
+[^:]*:68: Error: r15 not allowed here -- `ldrb r0,\[r1,pc\]'
+[^:]*:69: Error: r15 not allowed here -- `ldrb.w pc,\[r0,r1,LSL#1\]'
+[^:]*:70: Error: r13 not allowed here -- `ldrb.w sp,\[r0,r1\]'
+[^:]*:71: Error: r15 not allowed here -- `ldrb.w r2,\[r0,pc,LSL#2\]'
+[^:]*:72: Error: r13 not allowed here -- `ldrb.w r2,\[r0,sp,LSL#2\]'
+[^:]*:75: Error: r15 not allowed here -- `ldrbt pc,\[r0,#4\]'
+[^:]*:76: Error: r13 not allowed here -- `ldrbt sp,\[r0,#4\]'
+[^:]*:79: Error: r15 not allowed here -- `ldrd pc,r0,\[r1\]'
+[^:]*:80: Error: r13 not allowed here -- `ldrd sp,r0,\[r1\]'
+[^:]*:81: Error: r15 not allowed here -- `ldrd r0,pc,\[r1\]'
+[^:]*:82: Error: r13 not allowed here -- `ldrd r0,sp,\[r1\]'
+[^:]*:83: Error: r15 not allowed here -- `ldrd pc,r0,\[r1\],#4'
+[^:]*:84: Error: r13 not allowed here -- `ldrd sp,r0,\[r1\],#4'
+[^:]*:85: Error: r15 not allowed here -- `ldrd r0,pc,\[r1\],#4'
+[^:]*:86: Error: r13 not allowed here -- `ldrd r0,sp,\[r1\],#4'
+[^:]*:87: Error: r15 not allowed here -- `ldrd pc,r0,\[r1,#4\]!'
+[^:]*:88: Error: r13 not allowed here -- `ldrd sp,r0,\[r1,#4\]!'
+[^:]*:89: Error: r15 not allowed here -- `ldrd r0,pc,\[r1,#4\]!'
+[^:]*:90: Error: r13 not allowed here -- `ldrd r0,sp,\[r1,#4\]!'
+[^:]*:93: Error: r15 not allowed here -- `ldrd pc,r0,label'
+[^:]*:94: Error: r13 not allowed here -- `ldrd sp,r0,label'
+[^:]*:95: Error: r15 not allowed here -- `ldrd r0,pc,label'
+[^:]*:96: Error: r13 not allowed here -- `ldrd r0,sp,label'
+[^:]*:97: Error: r15 not allowed here -- `ldrd pc,r0,\[pc,#-0\]'
+[^:]*:98: Error: r13 not allowed here -- `ldrd sp,r0,\[pc,#-0\]'
+[^:]*:99: Error: r15 not allowed here -- `ldrd r0,pc,\[pc,#-0\]'
+[^:]*:100: Error: r13 not allowed here -- `ldrd r0,sp,\[pc,#-0\]'
+[^:]*:105: Error: r15 not allowed here -- `ldrex pc,\[r0\]'
+[^:]*:106: Error: r13 not allowed here -- `ldrex sp,\[r0\]'
+[^:]*:107: Error: r15 not allowed here -- `ldrex r0,\[pc\]'
+[^:]*:108: Error: r15 not allowed here -- `ldrexb pc,\[r0\]'
+[^:]*:109: Error: r13 not allowed here -- `ldrexb sp,\[r0\]'
+[^:]*:110: Error: r15 not allowed here -- `ldrexb r0,\[pc\]'
+[^:]*:111: Error: r15 not allowed here -- `ldrexd pc,r0,\[r1\]'
+[^:]*:112: Error: r13 not allowed here -- `ldrexd sp,r0,\[r1\]'
+[^:]*:113: Error: r15 not allowed here -- `ldrexd r0,pc,\[r1\]'
+[^:]*:114: Error: r13 not allowed here -- `ldrexd r0,sp,\[r1\]'
+[^:]*:115: Error: r15 not allowed here -- `ldrexd r0,r1,\[pc\]'
+[^:]*:116: Error: r15 not allowed here -- `ldrexh pc,\[r0\]'
+[^:]*:117: Error: r13 not allowed here -- `ldrexh sp,\[r0\]'
+[^:]*:118: Error: r15 not allowed here -- `ldrexh r0,\[pc\]'
+[^:]*:121: Error: r15 not allowed here -- `ldrh pc,\[r0\]'
+[^:]*:122: Error: r15 not allowed here -- `ldrh pc,\[r0,#4\]'
+[^:]*:125: Error: r15 not allowed here -- `ldrh.w pc,\[r0\]'
+[^:]*:126: Error: r15 not allowed here -- `ldrh.w pc,\[r0,#4\]'
+[^:]*:127: Error: r13 not allowed here -- `ldrh.w sp,\[r0\]'
+[^:]*:128: Error: r13 not allowed here -- `ldrh.w sp,\[r0,#4\]'
+[^:]*:129: Error: r15 not allowed here -- `ldrh pc,\[r0,#-3\]'
+[^:]*:131: Error: r15 not allowed here -- `ldrh pc,\[r0\],#4'
+[^:]*:132: Error: r13 not allowed here -- `ldrh sp,\[r0\],#4'
+[^:]*:133: Error: r15 not allowed here -- `ldrh pc,\[r0,#4\]!'
+[^:]*:134: Error: r13 not allowed here -- `ldrh sp,\[r0,#4\]!'
+[^:]*:137: Error: r15 not allowed here -- `ldrh pc,label'
+[^:]*:138: Error: r15 not allowed here -- `ldrh pc,\[pc,#-0\]'
+[^:]*:139: Error: r13 not allowed here -- `ldrh sp,label'
+[^:]*:140: Error: r13 not allowed here -- `ldrh sp,\[pc,#-0\]'
+[^:]*:143: Error: r15 not allowed here -- `ldrh pc,\[r0,r1\]'
+[^:]*:144: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[pc,r1\]'
+[^:]*:145: Error: r15 not allowed here -- `ldrh r0,\[r1,pc\]'
+[^:]*:146: Error: r15 not allowed here -- `ldrh.w pc,\[r0,r1,LSL#1\]'
+[^:]*:147: Error: r13 not allowed here -- `ldrh.w sp,\[r0,r1,LSL#1\]'
+[^:]*:148: Error: r15 not allowed here -- `ldrh.w r2,\[r0,pc,LSL#1\]'
+[^:]*:149: Error: r13 not allowed here -- `ldrh.w r2,\[r0,sp,LSL#1\]'
+[^:]*:152: Error: r15 not allowed here -- `ldrht pc,\[r0,#4\]'
+[^:]*:153: Error: r13 not allowed here -- `ldrht sp,\[r0,#4\]'
+[^:]*:156: Error: r15 not allowed here -- `ldrsb pc,\[r0,#4\]'
+[^:]*:158: Error: r13 not allowed here -- `ldrsb sp,\[r0,#4\]'
+[^:]*:159: Error: r15 not allowed here -- `ldrsb pc,\[r0,#-4\]'
+[^:]*:160: Error: r13 not allowed here -- `ldrsb sp,\[r0,#-4\]'
+[^:]*:161: Error: r15 not allowed here -- `ldrsb pc,\[r0\],#4'
+[^:]*:162: Error: r13 not allowed here -- `ldrsb sp,\[r0\],#4'
+[^:]*:163: Error: r15 not allowed here -- `ldrsb pc,\[r0,#4\]!'
+[^:]*:164: Error: r13 not allowed here -- `ldrsb sp,\[r0,#4\]!'
+[^:]*:167: Error: r15 not allowed here -- `ldrsb pc,label'
+[^:]*:168: Error: r15 not allowed here -- `ldrsb pc,\[pc,#-0\]'
+[^:]*:169: Error: r13 not allowed here -- `ldrsb sp,label'
+[^:]*:170: Error: r13 not allowed here -- `ldrsb sp,\[pc,#-0\]'
+[^:]*:173: Error: r15 not allowed here -- `ldrsb pc,\[r0,r1\]'
+[^:]*:174: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[pc,r1\]'
+[^:]*:175: Error: r15 not allowed here -- `ldrsb r0,\[r1,pc\]'
+[^:]*:176: Error: r15 not allowed here -- `ldrsb.w pc,\[r0,r1,LSL#2\]'
+[^:]*:178: Error: r13 not allowed here -- `ldrsb.w sp,\[r0,r1,LSL#2\]'
+[^:]*:179: Error: r15 not allowed here -- `ldrsb.w r2,\[r0,pc,LSL#2\]'
+[^:]*:180: Error: r13 not allowed here -- `ldrsb.w r2,\[r0,sp,LSL#2\]'
+[^:]*:184: Error: r15 not allowed here -- `ldrsbt pc,\[r0,#4\]'
+[^:]*:185: Error: r13 not allowed here -- `ldrsbt sp,\[r0,#4\]'
+[^:]*:189: Error: r15 not allowed here -- `ldrsh pc,\[r0,#4\]'
+[^:]*:190: Error: r13 not allowed here -- `ldrsh sp,\[r0,#4\]'
+[^:]*:191: Error: r15 not allowed here -- `ldrsh pc,\[r0,#-4\]'
+[^:]*:192: Error: r15 not allowed here -- `ldrsh pc,\[r0\],#4'
+[^:]*:193: Error: r15 not allowed here -- `ldrsh pc,\[r0,#4\]!'
+[^:]*:194: Error: r13 not allowed here -- `ldrsh sp,\[r0,#-4\]'
+[^:]*:195: Error: r13 not allowed here -- `ldrsh sp,\[r0\],#4'
+[^:]*:196: Error: r13 not allowed here -- `ldrsh sp,\[r0,#4\]!'
+[^:]*:199: Error: r15 not allowed here -- `ldrsh pc,label'
+[^:]*:200: Error: r13 not allowed here -- `ldrsh sp,label'
+[^:]*:201: Error: r13 not allowed here -- `ldrsh sp,\[pc,#-0\]'
+[^:]*:204: Error: r15 not allowed here -- `ldrsh pc,\[r0,r1\]'
+[^:]*:205: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[pc,r1\]'
+[^:]*:206: Error: r15 not allowed here -- `ldrsh r0,\[r1,pc\]'
+[^:]*:208: Error: r15 not allowed here -- `ldrsh.w pc,\[r0,r1,LSL#3\]'
+[^:]*:209: Error: r13 not allowed here -- `ldrsh.w sp,\[r0,r1,LSL#3\]'
+[^:]*:210: Error: r13 not allowed here -- `ldrsh.w r0,\[r1,sp,LSL#3\]'
+[^:]*:211: Error: r15 not allowed here -- `ldrsh.w r0,\[r1,pc,LSL#3\]'
+[^:]*:215: Error: r15 not allowed here -- `ldrsht pc,\[r0,#4\]'
+[^:]*:216: Error: r13 not allowed here -- `ldrsht sp,\[r0,#4\]'
+[^:]*:220: Error: r15 not allowed here -- `ldrt pc,\[r0,#4\]'
+[^:]*:221: Error: r13 not allowed here -- `ldrt sp,\[r0,#4\]'
+[^:]*:226: Error: r15 not allowed here -- `str pc,\[r0,#4\]'
+[^:]*:227: Error: cannot use register index with PC-relative addressing -- `str.w r0,\[pc,#4\]'
+[^:]*:228: Error: cannot use register index with PC-relative addressing -- `str r0,\[pc,#-4\]'
+[^:]*:229: Error: cannot use post-indexing with PC-relative addressing -- `str r0,\[pc\],#4'
+[^:]*:230: Error: cannot use writeback with PC-relative addressing -- `str r0,\[pc,#4\]!'
+[^:]*:233: Error: cannot use register index with PC-relative addressing -- `str.w r0,\[pc,r1\]'
+[^:]*:234: Error: cannot use register index with PC-relative addressing -- `str.w r0,\[pc,r1,LSL#2\]'
+[^:]*:240: Error: cannot use register index with PC-relative addressing -- `strb.w r0,\[pc,#4\]'
+[^:]*:241: Error: r15 not allowed here -- `strb.w pc,\[r0,#4\]'
+[^:]*:242: Error: r13 not allowed here -- `strb.w sp,\[r0,#4\]'
+[^:]*:243: Error: cannot use register index with PC-relative addressing -- `strb r0,\[pc,#-4\]'
+[^:]*:244: Error: cannot use post-indexing with PC-relative addressing -- `strb r0,\[pc\],#4'
+[^:]*:245: Error: cannot use writeback with PC-relative addressing -- `strb r0,\[pc,#4\]!'
+[^:]*:246: Error: r15 not allowed here -- `strb pc,\[r0,#-4\]'
+[^:]*:247: Error: r15 not allowed here -- `strb pc,\[r0\],#4'
+[^:]*:248: Error: r15 not allowed here -- `strb pc,\[r0,#4\]!'
+[^:]*:249: Error: r13 not allowed here -- `strb sp,\[r0,#-4\]'
+[^:]*:250: Error: r13 not allowed here -- `strb sp,\[r0\],#4'
+[^:]*:251: Error: r13 not allowed here -- `strb sp,\[r0,#4\]!'
+[^:]*:254: Error: cannot use register index with PC-relative addressing -- `strb.w r0,\[pc,r1\]'
+[^:]*:255: Error: cannot use register index with PC-relative addressing -- `strb.w r0,\[pc,r1,LSL#2\]'
+[^:]*:256: Error: r15 not allowed here -- `strb.w pc,\[r0,r1\]'
+[^:]*:257: Error: r15 not allowed here -- `strb.w pc,\[r0,r1,LSL#2\]'
+[^:]*:258: Error: r13 not allowed here -- `strb.w sp,\[r0,r1\]'
+[^:]*:259: Error: r13 not allowed here -- `strb.w sp,\[r0,r1,LSL#2\]'
+[^:]*:260: Error: r15 not allowed here -- `strb.w r0,\[r1,pc\]'
+[^:]*:261: Error: r15 not allowed here -- `strb.w r0,\[r1,pc,LSL#2\]'
+[^:]*:262: Error: r13 not allowed here -- `strb.w r0,\[r1,sp\]'
+[^:]*:263: Error: r13 not allowed here -- `strb.w r0,\[r1,sp,LSL#2\]'
+[^:]*:266: Error: cannot use register index with PC-relative addressing -- `strbt r0,\[pc,#4\]'
+[^:]*:267: Error: r15 not allowed here -- `strbt pc,\[r0,#4\]'
+[^:]*:268: Error: r13 not allowed here -- `strbt sp,\[r0,#4\]'
+[^:]*:271: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[pc,#4\]'
+[^:]*:272: Error: cannot use post-indexing with PC-relative addressing -- `strd r0,r1,\[pc\],#4'
+[^:]*:273: Error: cannot use writeback with PC-relative addressing -- `strd r0,r1,\[pc,#4\]!'
+[^:]*:274: Error: r15 not allowed here -- `strd pc,r0,\[r1,#4\]'
+[^:]*:275: Error: r15 not allowed here -- `strd pc,r0,\[r1\],#4'
+[^:]*:276: Error: r15 not allowed here -- `strd pc,r0,\[r1,#4\]!'
+[^:]*:277: Error: r13 not allowed here -- `strd sp,r0,\[r1,#4\]'
+[^:]*:278: Error: r13 not allowed here -- `strd sp,r0,\[r1\],#4'
+[^:]*:279: Error: r13 not allowed here -- `strd sp,r0,\[r1,#4\]!'
+[^:]*:280: Error: r15 not allowed here -- `strd r0,pc,\[r1,#4\]'
+[^:]*:281: Error: r15 not allowed here -- `strd r0,pc,\[r1\],#4'
+[^:]*:282: Error: r15 not allowed here -- `strd r0,pc,\[r1,#4\]!'
+[^:]*:283: Error: r13 not allowed here -- `strd r0,sp,\[r1,#4\]'
+[^:]*:284: Error: r13 not allowed here -- `strd r0,sp,\[r1\],#4'
+[^:]*:285: Error: r13 not allowed here -- `strd r0,sp,\[r1,#4\]!'
+[^:]*:291: Error: r15 not allowed here -- `strex pc,r0,\[r1\]'
+[^:]*:292: Error: r15 not allowed here -- `strex pc,r0,\[r1,#4\]'
+[^:]*:293: Error: r13 not allowed here -- `strex sp,r0,\[r1\]'
+[^:]*:294: Error: r13 not allowed here -- `strex sp,r0,\[r1,#4\]'
+[^:]*:295: Error: r15 not allowed here -- `strex r0,pc,\[r1\]'
+[^:]*:296: Error: r15 not allowed here -- `strex r0,pc,\[r1,#4\]'
+[^:]*:297: Error: r13 not allowed here -- `strex r0,sp,\[r1\]'
+[^:]*:298: Error: r13 not allowed here -- `strex r0,sp,\[r1,#4\]'
+[^:]*:299: Error: r15 not allowed here -- `strex r0,r1,\[pc\]'
+[^:]*:300: Error: r15 not allowed here -- `strex r0,r1,\[pc,#4\]'
+[^:]*:303: Error: r15 not allowed here -- `strexb pc,r0,\[r1\]'
+[^:]*:304: Error: r13 not allowed here -- `strexb sp,r0,\[r1\]'
+[^:]*:305: Error: r15 not allowed here -- `strexb r0,pc,\[r1\]'
+[^:]*:306: Error: r13 not allowed here -- `strexb r0,sp,\[r1\]'
+[^:]*:307: Error: r15 not allowed here -- `strexb r0,r1,\[pc\]'
+[^:]*:310: Error: r15 not allowed here -- `strexd pc,r0,r1,\[r2\]'
+[^:]*:311: Error: r13 not allowed here -- `strexd sp,r0,r1,\[r2\]'
+[^:]*:312: Error: r15 not allowed here -- `strexd r0,pc,r1,\[r2\]'
+[^:]*:313: Error: r13 not allowed here -- `strexd r0,sp,r1,\[r2\]'
+[^:]*:314: Error: r15 not allowed here -- `strexd r0,r1,pc,\[r2\]'
+[^:]*:315: Error: r13 not allowed here -- `strexd r0,r1,sp,\[r2\]'
+[^:]*:316: Error: r15 not allowed here -- `strexd r0,r1,r2,\[pc\]'
+[^:]*:319: Error: r15 not allowed here -- `strexh pc,r0,\[r1\]'
+[^:]*:320: Error: r13 not allowed here -- `strexh sp,r0,\[r1\]'
+[^:]*:321: Error: r15 not allowed here -- `strexh r0,pc,\[r1\]'
+[^:]*:322: Error: r13 not allowed here -- `strexh r0,sp,\[r1\]'
+[^:]*:323: Error: r15 not allowed here -- `strexh r0,r1,\[pc\]'
+[^:]*:326: Error: cannot use register index with PC-relative addressing -- `strh.w r0,\[pc\]'
+[^:]*:327: Error: cannot use register index with PC-relative addressing -- `strh.w r0,\[pc,#4\]'
+[^:]*:328: Error: cannot use register index with PC-relative addressing -- `strh r0,\[pc,#-4\]'
+[^:]*:329: Error: cannot use post-indexing with PC-relative addressing -- `strh r0,\[pc\],#4'
+[^:]*:330: Error: cannot use writeback with PC-relative addressing -- `strh r0,\[pc,#4\]!'
+[^:]*:333: Error: cannot use register index with PC-relative addressing -- `strh.w r0,\[pc,r1\]'
+[^:]*:334: Error: cannot use register index with PC-relative addressing -- `strh.w r0,\[pc,r1,LSL#2\]'
+[^:]*:335: Error: r15 not allowed here -- `strh.w pc,\[r0,#4\]'
+[^:]*:336: Error: r15 not allowed here -- `strh.w pc,\[r0\]'
+[^:]*:337: Error: r13 not allowed here -- `strh.w sp,\[r0,#4\]'
+[^:]*:338: Error: r13 not allowed here -- `strh.w sp,\[r0\]'
+[^:]*:339: Error: r15 not allowed here -- `strh pc,\[r0,#-4\]'
+[^:]*:340: Error: r15 not allowed here -- `strh pc,\[r0\],#4'
+[^:]*:341: Error: r15 not allowed here -- `strh pc,\[r0,#4\]!'
+[^:]*:342: Error: r13 not allowed here -- `strh sp,\[r0,#-4\]'
+[^:]*:343: Error: r13 not allowed here -- `strh sp,\[r0\],#4'
+[^:]*:344: Error: r13 not allowed here -- `strh sp,\[r0,#4\]!'
+[^:]*:345: Error: r15 not allowed here -- `strh.w pc,\[r0,r1\]'
+[^:]*:346: Error: r13 not allowed here -- `strh.w sp,\[r0,r1\]'
+[^:]*:347: Error: r15 not allowed here -- `strh.w r0,\[r1,pc\]'
+[^:]*:348: Error: r13 not allowed here -- `strh.w r0,\[r1,sp\]'
+[^:]*:349: Error: r15 not allowed here -- `strh.w pc,\[r0,r1,LSL#2\]'
+[^:]*:350: Error: r13 not allowed here -- `strh.w sp,\[r0,r1,LSL#2\]'
+[^:]*:351: Error: r15 not allowed here -- `strh.w r0,\[r1,pc,LSL#2\]'
+[^:]*:352: Error: r13 not allowed here -- `strh.w r0,\[r1,sp,LSL#2\]'
+[^:]*:355: Error: cannot use register index with PC-relative addressing -- `strht r0,\[pc,#4\]'
+[^:]*:356: Error: r15 not allowed here -- `strht pc,\[r0,#4\]'
+[^:]*:357: Error: r13 not allowed here -- `strht sp,\[pc,#4\]'
+[^:]*:360: Error: cannot use register index with PC-relative addressing -- `strt r0,\[pc,#4\]'
+[^:]*:361: Error: r15 not allowed here -- `strt pc,\[r0,#4\]'
+[^:]*:362: Error: r13 not allowed here -- `strt sp,\[r0,#4\]'
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad-t.s b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.s
new file mode 100644
index 0000000..4252cba
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad-t.s
@@ -0,0 +1,367 @@
+.syntax unified
+.thumb
+
+.macro it_test opcode operands:vararg
+itt eq
+\opcode\()eq r15, \operands
+moveq r0, r0
+.endm
+
+.macro it_testw opcode operands:vararg
+itt eq
+\opcode\()eq.w r15, \operands
+moveq r0, r0
+.endm
+
+.macro LOAD operands:vararg
+it_test ldr, \operands
+.endm
+
+.macro LOADw operands:vararg
+it_testw ldr, \operands
+.endm
+
+@ Loads ===============================================================
+
+@ LDR (register)
+LOAD [r0]
+LOAD [r0,#0]
+LOAD [sp]
+LOAD [sp,#0]
+LOADw [r0]
+LOADw [r0,#0]
+LOAD [r0,#-4]
+LOAD [r0],#4
+LOAD [r0,#0]!
+
+@ LDR (literal)
+LOAD label
+LOADw label
+LOADw [pc, #-0]
+
+@ LDR (register)
+LOAD [r0, r1]
+LOADw [r0, r1]
+LOADw [r0, r1, LSL #2]
+
+@ LDRB (immediate, Thumb)
+ldrb pc, [r0,#4] @ low reg
+@ldrb r0, [pc,#4] @ ALLOWED!
+ldrb.w sp, [r0,#4] @ Unpredictable
+ldrb.w pc, [r0,#4] @ => PLD
+ldrb pc, [r0, #-4] @ => PLD
+@ LDRB<c><q> <Rt>, [<Rn>, #+<imm>] => See LDRBT
+ldrb pc, [r0],#4 @ BadReg
+ldrb sp, [r0],#4 @ ditto
+ldrb pc,[r0,#4]! @ ditto
+ldrb sp,[r0,#4]! @ ditto
+
+@ LDRB (literal)
+ldrb pc,label @ => PLD
+ldrb pc,[PC,#-0] @ => PLD (special case)
+ldrb sp,label @ Unpredictable
+ldrb sp,[PC,#-0] @ ditto
+
+@ LDRB (register)
+ldrb pc,[r0,r1] @ low reg
+ldrb r0,[pc,r1] @ ditto
+ldrb r0,[r1,pc] @ ditto
+ldrb.w pc,[r0,r1,LSL #1] @ => PLD
+ldrb.w sp,[r0,r1] @ Unpredictable
+ldrb.w r2,[r0,pc,LSL #2] @ BadReg
+ldrb.w r2,[r0,sp,LSL #2] @ ditto
+
+@ LDRBT
+ldrbt pc, [r0, #4] @ BadReg
+ldrbt sp, [r0, #4] @ ditto
+
+@ LDRD (immediate)
+ldrd pc, r0, [r1] @ BadReg
+ldrd sp, r0, [r1] @ ditto
+ldrd r0, pc, [r1] @ ditto
+ldrd r0, sp, [r1] @ ditto
+ldrd pc, r0, [r1], #4 @ ditto
+ldrd sp, r0, [r1], #4 @ ditto
+ldrd r0, pc, [r1], #4 @ ditto
+ldrd r0, sp, [r1], #4 @ ditto
+ldrd pc, r0, [r1, #4]! @ ditto
+ldrd sp, r0, [r1, #4]! @ ditto
+ldrd r0, pc, [r1, #4]! @ ditto
+ldrd r0, sp, [r1, #4]! @ ditto
+
+@ LDRD (literal)
+ldrd pc, r0, label @ BadReg
+ldrd sp, r0, label @ ditto
+ldrd r0, pc, label @ ditto
+ldrd r0, sp, label @ ditto
+ldrd pc, r0, [pc, #-0] @ ditto
+ldrd sp, r0, [pc, #-0] @ ditto
+ldrd r0, pc, [pc, #-0] @ ditto
+ldrd r0, sp, [pc, #-0] @ ditto
+
+@ LDRD (register): ARM only
+
+@ LDREX/B/D/H
+ldrex pc, [r0] @ BadReg
+ldrex sp, [r0] @ ditto
+ldrex r0, [pc] @ Unpredictable
+ldrexb pc, [r0] @ BadReg
+ldrexb sp, [r0] @ ditto
+ldrexb r0, [pc] @ Unpredictable
+ldrexd pc, r0, [r1] @ BadReg
+ldrexd sp, r0, [r1] @ ditto
+ldrexd r0, pc, [r1] @ ditto
+ldrexd r0, sp, [r1] @ ditto
+ldrexd r0, r1, [pc] @ Unpredictable
+ldrexh pc, [r0] @ BadReg
+ldrexh sp, [r0] @ ditto
+ldrexh r0, [pc] @ Unpredictable
+
+@ LDRH (immediate)
+ldrh pc, [r0] @ low reg
+ldrh pc, [r0, #4] @ ditto
+@ldrh r0, [pc] @ ALLOWED!
+@ldrh r0, [pc, #4] @ ditto
+ldrh.w pc, [r0] @ => Unallocated memory hints
+ldrh.w pc, [r0, #4] @ ditto
+ldrh.w sp, [r0] @ Unpredictable
+ldrh.w sp, [r0, #4] @ ditto
+ldrh pc, [r0, #-3] @ => Unallocated memory hint
+@ LDRH<c><q> <Rt>, [<Rn>, #+<imm>] => See LDRHT
+ldrh pc,[r0],#4 @ BadReg
+ldrh sp,[r0],#4 @ ditto
+ldrh pc,[r0,#4]! @ ditto
+ldrh sp,[r0,#4]! @ ditto
+
+@ LDRH (literal)
+ldrh pc, label @ Unallocated memory hint
+ldrh pc, [pc, #-0] @ ditto
+ldrh sp, label @ Unpredictable
+ldrh sp, [pc, #-0] @ ditto
+
+@ LDRH (register)
+ldrh pc, [r0, r1] @ low reg
+ldrh r0, [pc, r1] @ ditto
+ldrh r0, [r1, pc] @ ditto
+ldrh.w pc,[r0,r1,LSL #1] @ => Unallocated memory hints
+ldrh.w sp,[r0,r1,LSL #1] @ Unpredictable
+ldrh.w r2,[r0,pc,LSL #1] @ ditto
+ldrh.w r2,[r0,sp,LSL #1] @ ditto
+
+@ LDRHT
+ldrht pc, [r0, #4] @ BadReg
+ldrht sp, [r0, #4] @ ditto
+
+@ LDRSB (immediate)
+ldrsb pc, [r0, #4] @ => PLI
+@ldrsb r0, [pc, #4] => LDRSB (literal)
+ldrsb sp, [r0, #4] @ Unpredictable
+ldrsb pc, [r0, #-4] @ => PLI
+ldrsb sp,[r0,#-4] @ BadReg
+ldrsb pc,[r0],#4 @ ditto
+ldrsb sp,[r0],#4 @ ditto
+ldrsb pc,[r0,#4]! @ ditto
+ldrsb sp,[r0,#4]! @ ditto
+
+@ LDRSB (literal)
+ldrsb pc, label @ => PLI
+ldrsb pc, [pc, #-0] @ => PLI
+ldrsb sp, label @ Unpredictable
+ldrsb sp, [pc, #-0] @ ditto
+
+@ LDRSB (register)
+ldrsb pc, [r0, r1] @ low reg
+ldrsb r0, [pc, r1] @ ditto
+ldrsb r0, [r1, pc] @ ditto
+ldrsb.w pc, [r0, r1, LSL #2] @ => PLI
+@ldrsb.w r0, [pc, r0, LSL #2] => LDRSB (literal)
+ldrsb.w sp, [r0, r1, LSL #2] @ Unpredictable
+ldrsb.w r2, [r0, pc, LSL #2] @ ditto
+ldrsb.w r2, [r0, sp, LSL #2] @ ditto
+
+@ LDRSBT
+@ldrsbt r0, [pc, #4] => LDRSB (literal)
+ldrsbt pc, [r0, #4] @ BadReg
+ldrsbt sp, [r0, #4] @ ditto
+
+@ LDRSH (immediate)
+@ldrsh r0,[pc,#4] => LDRSH (literal)
+ldrsh pc,[r0,#4] @ => Unallocated memory hints
+ldrsh sp,[r0,#4] @ Unpredictable
+ldrsh pc, [r0, #-4] @ => Unallocated memory hints
+ldrsh pc,[r0],#4 @ BadReg
+ldrsh pc,[r0,#4]! @ ditto
+ldrsh sp,[r0,#-4] @ ditto
+ldrsh sp,[r0],#4 @ ditto
+ldrsh sp,[r0,#4]! @ ditto
+
+@ LDRSH (literal)
+ldrsh pc, label @ => Unallocated memory hints
+ldrsh sp, label @ Unpredictable
+ldrsh sp, [pc,#-0] @ ditto
+
+@ LDRSH (register)
+ldrsh pc,[r0,r1] @ low reg
+ldrsh r0,[pc,r1] @ ditto
+ldrsh r0,[r1,pc] @ ditto
+@ldrsh.w r0,[pc,r1,LSL #3] => LDRSH (literal)
+ldrsh.w pc,[r0,r1,LSL #3] @ => Unallocated memory hints
+ldrsh.w sp,[r0,r1,LSL #3] @ Unpredictable
+ldrsh.w r0,[r1,sp,LSL #3] @ BadReg
+ldrsh.w r0,[r1,pc,LSL #3] @ ditto
+
+@ LDRSHT
+@ldrsht r0,[pc,#4] => LDRSH (literal)
+ldrsht pc,[r0,#4] @ BadReg
+ldrsht sp,[r0,#4] @ ditto
+
+@ LDRT
+@ldrt r0,[pc,#4] => LDR (literal)
+ldrt pc,[r0,#4] @ BadReg
+ldrt sp,[r0,#4] @ ditto
+
+@ Stores ==============================================================
+
+@ STR (immediate, Thumb)
+str pc, [r0, #4] @ Unpredictable
+str.w r0, [pc, #4] @ Undefined
+str r0, [pc, #-4] @ ditto
+str r0, [pc], #4 @ ditto
+str r0, [pc, #4]! @ ditto
+
+@ STR (register)
+str.w r0,[pc,r1] @ Undefined
+str.w r0,[pc,r1,LSL #2] @ ditto
+@str.w pc,[r0,r1{,LSL #<imm2>}] @ Unpredictable
+@str.w r1,[r0,sp{,LSL #<imm2>}] @ ditto
+@str.w r1,[r0,pc{,LSL #<imm2>}] @ ditto
+
+@ STRB (immediate, Thumb)
+strb.w r0,[pc,#4] @ Undefined
+strb.w pc,[r0,#4] @ Unpredictable
+strb.w sp,[r0,#4] @ ditto
+strb r0,[pc,#-4] @ Undefined
+strb r0,[pc],#4 @ ditto
+strb r0,[pc,#4]! @ ditto
+strb pc,[r0,#-4] @ Unpredictable
+strb pc,[r0],#4 @ ditto
+strb pc,[r0,#4]! @ ditto
+strb sp,[r0,#-4] @ ditto
+strb sp,[r0],#4 @ ditto
+strb sp,[r0,#4]! @ ditto
+
+@ STRB (register)
+strb.w r0,[pc,r1] @ Undefined
+strb.w r0,[pc,r1,LSL #2] @ ditto
+strb.w pc,[r0,r1] @ Unpredictable
+strb.w pc,[r0,r1,LSL #2] @ ditto
+strb.w sp,[r0,r1] @ ditto
+strb.w sp,[r0,r1,LSL #2] @ ditto
+strb.w r0,[r1,pc] @ ditto
+strb.w r0,[r1,pc,LSL #2] @ ditto
+strb.w r0,[r1,sp] @ ditto
+strb.w r0,[r1,sp,LSL #2] @ ditto
+
+@ STRBT
+strbt r0,[pc,#4] @ Undefined
+strbt pc,[r0,#4] @ Unpredictable
+strbt sp,[r0,#4] @ ditto
+
+@ STRD (immediate)
+strd r0,r1,[pc,#4] @ Unpredictable
+strd r0,r1,[pc],#4 @ ditto
+strd r0,r1,[pc,#4]! @ ditto
+strd pc,r0,[r1,#4] @ ditto
+strd pc,r0,[r1],#4 @ ditto
+strd pc,r0,[r1,#4]! @ ditto
+strd sp,r0,[r1,#4] @ ditto
+strd sp,r0,[r1],#4 @ ditto
+strd sp,r0,[r1,#4]! @ ditto
+strd r0,pc,[r1,#4] @ ditto
+strd r0,pc,[r1],#4 @ ditto
+strd r0,pc,[r1,#4]! @ ditto
+strd r0,sp,[r1,#4] @ ditto
+strd r0,sp,[r1],#4 @ ditto
+strd r0,sp,[r1,#4]! @ ditto
+
+@ STRD (register)
+@No thumb.
+
+@ STREX
+strex pc,r0,[r1] @ Unpredictable
+strex pc,r0,[r1,#4] @ ditto
+strex sp,r0,[r1] @ ditto
+strex sp,r0,[r1,#4] @ ditto
+strex r0,pc,[r1] @ ditto
+strex r0,pc,[r1,#4] @ ditto
+strex r0,sp,[r1] @ ditto
+strex r0,sp,[r1,#4] @ ditto
+strex r0,r1,[pc] @ ditto
+strex r0,r1,[pc,#4] @ ditto
+
+@ STREXB
+strexb pc,r0,[r1] @ Unpredictable
+strexb sp,r0,[r1] @ ditto
+strexb r0,pc,[r1] @ ditto
+strexb r0,sp,[r1] @ ditto
+strexb r0,r1,[pc] @ ditto
+
+@ STREXD
+strexd pc,r0,r1,[r2] @ Unpredictable
+strexd sp,r0,r1,[r2] @ ditto
+strexd r0,pc,r1,[r2] @ ditto
+strexd r0,sp,r1,[r2] @ ditto
+strexd r0,r1,pc,[r2] @ ditto
+strexd r0,r1,sp,[r2] @ ditto
+strexd r0,r1,r2,[pc] @ ditto
+
+@ STREXH
+strexh pc,r0,[r1] @ Unpredictable
+strexh sp,r0,[r1] @ ditto
+strexh r0,pc,[r1] @ ditto
+strexh r0,sp,[r1] @ ditto
+strexh r0,r1,[pc] @ ditto
+
+@ STRH (immediate, Thumb)
+strh.w r0,[pc] @ Undefined
+strh.w r0,[pc,#4] @ ditto
+strh r0,[pc,#-4] @ ditto
+strh r0,[pc],#4 @ ditto
+strh r0,[pc,#4]! @ ditto
+
+@ STRH (register)
+strh.w r0,[pc,r1] @ Undefined
+strh.w r0,[pc,r1,LSL #2] @ ditto
+strh.w pc,[r0,#4] @ Unpredictable
+strh.w pc,[r0] @ ditto
+strh.w sp,[r0,#4] @ ditto
+strh.w sp,[r0] @ ditto
+strh pc,[r0,#-4] @ ditto
+strh pc,[r0],#4 @ ditto
+strh pc,[r0,#4]! @ ditto
+strh sp,[r0,#-4] @ ditto
+strh sp,[r0],#4 @ ditto
+strh sp,[r0,#4]! @ ditto
+strh.w pc,[r0,r1] @ ditto
+strh.w sp,[r0,r1] @ ditto
+strh.w r0,[r1,pc] @ ditto
+strh.w r0,[r1,sp] @ ditto
+strh.w pc,[r0,r1,LSL #2] @ ditto
+strh.w sp,[r0,r1,LSL #2] @ ditto
+strh.w r0,[r1,pc,LSL #2] @ ditto
+strh.w r0,[r1,sp,LSL #2] @ ditto
+
+@ STRHT
+strht r0,[pc,#4] @ Undefined
+strht pc,[r0,#4] @ Unpredictable
+strht sp,[pc,#4] @ ditto
+
+@ STRT
+strt r0,[pc,#4] @ Undefined
+strt pc,[r0,#4] @ Unpredictable
+strt sp,[r0,#4] @ ditto
+
+@ ============================================================================
+
+.label:
+ldr r0, [r1]
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad.d b/gas/testsuite/gas/arm/sp-pc-validations-bad.d
new file mode 100644
index 0000000..558a683
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad.d
@@ -0,0 +1,2 @@
+# name: Invalid SP and PC operands test - ARM
+# error-output: sp-pc-validations-bad.l
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad.l b/gas/testsuite/gas/arm/sp-pc-validations-bad.l
new file mode 100644
index 0000000..002dbb2
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad.l
@@ -0,0 +1,172 @@
+[^:]*: Assembler messages:
+[^:]*:11: Error: cannot use register index with PC-relative addressing -- `ldr r0,\[r1,pc,LSL#2\]'
+[^:]*:12: Error: cannot use register index with PC-relative addressing -- `ldr r0,\[r1,pc,LSL#2\]!'
+[^:]*:13: Error: cannot use register index with PC-relative addressing -- `ldr r0,\[r1\],pc,LSL#2'
+[^:]*:14: Error: cannot use register index with PC-relative addressing -- `ldr r0,\[pc,r1,LSL#2\]!'
+[^:]*:15: Error: cannot use register index with PC-relative addressing -- `ldr r0,\[pc\],r1,LSL#2'
+[^:]*:18: Error: r15 not allowed here -- `ldrb pc,\[r0,#4\]'
+[^:]*:19: Error: r15 not allowed here -- `ldrb pc,\[r0\],#4'
+[^:]*:20: Error: r15 not allowed here -- `ldrb pc,\[r0,#4\]!'
+[^:]*:23: Error: r15 not allowed here -- `ldrb pc,label'
+[^:]*:24: Error: r15 not allowed here -- `ldrb pc,\[pc,#-0\]'
+[^:]*:27: Error: r15 not allowed here -- `ldrb pc,\[r0,r1,LSL#2\]'
+[^:]*:28: Error: r15 not allowed here -- `ldrb pc,\[r0,r1,LSL#2\]!'
+[^:]*:29: Error: r15 not allowed here -- `ldrb pc,\[r0\],r1,LSL#2'
+[^:]*:30: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[r1,pc,LSL#2\]'
+[^:]*:31: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[r1,pc,LSL#2\]!'
+[^:]*:32: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[r1\],pc,LSL#2'
+[^:]*:33: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[pc,r1,LSL#2\]!'
+[^:]*:34: Error: cannot use register index with PC-relative addressing -- `ldrb r0,\[pc\],r1,LSL#2'
+[^:]*:37: Error: r15 not allowed here -- `ldrbt pc,\[r0\],#4'
+[^:]*:38: Error: cannot use register index with PC-relative addressing -- `ldrbt r0,\[pc\],#4'
+[^:]*:39: Error: r15 not allowed here -- `ldrbt pc,\[r0\],r1,LSL#4'
+[^:]*:40: Error: cannot use register index with PC-relative addressing -- `ldrbt r0,\[pc\],r1,LSL#4'
+[^:]*:41: Error: cannot use register index with PC-relative addressing -- `ldrbt r0,\[r1\],pc,LSL#4'
+[^:]*:44: Error: r15 not allowed here -- `ldrd r0,pc,\[r1,#4\]'
+[^:]*:45: Error: r15 not allowed here -- `ldrd r0,pc,\[r1\],#4'
+[^:]*:46: Error: r15 not allowed here -- `ldrd r0,pc,\[r1,#4\]!'
+[^:]*:49: Error: r15 not allowed here -- `ldrd r0,pc,label'
+[^:]*:50: Error: r15 not allowed here -- `ldrd r0,pc,\[PC,#-0\]'
+[^:]*:53: Error: r15 not allowed here -- `ldrd r0,pc,\[r1,r2\]'
+[^:]*:54: Error: r15 not allowed here -- `ldrd r0,pc,\[r1,r2\]!'
+[^:]*:55: Error: r15 not allowed here -- `ldrd r0,pc,\[r1\],r2'
+[^:]*:56: Error: cannot use register index with PC-relative addressing -- `ldrd r0,r1,\[r2,pc\]'
+[^:]*:57: Error: cannot use register index with PC-relative addressing -- `ldrd r0,r1,\[r2,pc\]!'
+[^:]*:58: Error: cannot use register index with PC-relative addressing -- `ldrd r0,r1,\[r2\],pc'
+[^:]*:59: Error: cannot use register index with PC-relative addressing -- `ldrd r0,r1,\[pc,r2\]!'
+[^:]*:60: Error: cannot use register index with PC-relative addressing -- `ldrd r0,r1,\[pc\],r2'
+[^:]*:63: Error: r15 not allowed here -- `ldrex pc,\[r0\]'
+[^:]*:64: Error: instruction does not accept this addressing mode -- `ldrex r0,\[pc\]'
+[^:]*:67: Error: r15 not allowed here -- `ldrexb pc,\[r0\]'
+[^:]*:68: Error: r15 not allowed here -- `ldrexb r0,\[pc\]'
+[^:]*:71: Error: r15 not allowed here -- `ldrexd r0,r1,\[pc\]'
+[^:]*:74: Error: r15 not allowed here -- `ldrexh pc,\[r0\]'
+[^:]*:75: Error: r15 not allowed here -- `ldrexh r0,\[pc\]'
+[^:]*:78: Error: r15 not allowed here -- `ldrh pc,\[r0,#4\]'
+[^:]*:79: Error: r15 not allowed here -- `ldrh pc,\[r0\],#4'
+[^:]*:80: Error: r15 not allowed here -- `ldrh pc,\[r0,#4\]!'
+[^:]*:83: Error: r15 not allowed here -- `ldrh pc,label'
+[^:]*:84: Error: r15 not allowed here -- `ldrh pc,\[pc,#-0\]'
+[^:]*:87: Error: r15 not allowed here -- `ldrh pc,\[r0,r1\]'
+[^:]*:88: Error: r15 not allowed here -- `ldrh pc,\[r0,r1\]!'
+[^:]*:89: Error: r15 not allowed here -- `ldrh pc,\[r0\],r1'
+[^:]*:90: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[r1,pc\]'
+[^:]*:91: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[r1,pc\]!'
+[^:]*:92: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[r1\],pc'
+[^:]*:93: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[pc,r1\]!'
+[^:]*:94: Error: cannot use register index with PC-relative addressing -- `ldrh r0,\[pc\],r1'
+[^:]*:97: Error: r15 not allowed here -- `ldrht pc,\[r0\],#4'
+[^:]*:98: Error: cannot use writeback with PC-relative addressing -- `ldrht r0,\[pc\],#4'
+[^:]*:99: Error: r15 not allowed here -- `ldrht pc,\[r0\],r1'
+[^:]*:100: Error: cannot use register index with PC-relative addressing -- `ldrht r0,\[pc\],r1'
+[^:]*:101: Error: cannot use register index with PC-relative addressing -- `ldrht r0,\[r1\],pc'
+[^:]*:104: Error: r15 not allowed here -- `ldrsb pc,\[r0,#4\]'
+[^:]*:105: Error: r15 not allowed here -- `ldrsb pc,\[r0\],#4'
+[^:]*:106: Error: r15 not allowed here -- `ldrsb pc,\[r0,#4\]!'
+[^:]*:109: Error: r15 not allowed here -- `ldrsb pc,label'
+[^:]*:110: Error: r15 not allowed here -- `ldrsb pc,\[pc,#-0\]'
+[^:]*:113: Error: r15 not allowed here -- `ldrsb pc,\[r0,r1\]'
+[^:]*:114: Error: r15 not allowed here -- `ldrsb pc,\[r0,r1\]!'
+[^:]*:115: Error: r15 not allowed here -- `ldrsb pc,\[r0\],r1'
+[^:]*:116: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[r1,pc\]'
+[^:]*:117: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[r1,pc\]!'
+[^:]*:118: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[r1\],pc'
+[^:]*:119: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[pc,r1\]!'
+[^:]*:120: Error: cannot use register index with PC-relative addressing -- `ldrsb r0,\[pc\],r1'
+[^:]*:123: Error: r15 not allowed here -- `ldrsbt pc,\[r0\],#4'
+[^:]*:124: Error: cannot use writeback with PC-relative addressing -- `ldrsbt r0,\[pc\],#4'
+[^:]*:125: Error: r15 not allowed here -- `ldrsbt pc,\[r0\],r1'
+[^:]*:126: Error: cannot use register index with PC-relative addressing -- `ldrsbt r0,\[pc\],r1'
+[^:]*:127: Error: cannot use register index with PC-relative addressing -- `ldrsbt r0,\[r1\],pc'
+[^:]*:130: Error: r15 not allowed here -- `ldrsh pc,\[r0,#4\]'
+[^:]*:131: Error: r15 not allowed here -- `ldrsh pc,\[r0\],#4'
+[^:]*:132: Error: r15 not allowed here -- `ldrsh pc,\[r0,#4\]!'
+[^:]*:135: Error: r15 not allowed here -- `ldrsh pc,label'
+[^:]*:136: Error: r15 not allowed here -- `ldrsh pc,\[pc,#-0\]'
+[^:]*:139: Error: r15 not allowed here -- `ldrsh pc,\[r0,r1\]'
+[^:]*:140: Error: r15 not allowed here -- `ldrsh pc,\[r0,r1\]!'
+[^:]*:141: Error: r15 not allowed here -- `ldrsh pc,\[r0\],r1'
+[^:]*:142: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[r1,pc\]'
+[^:]*:143: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[r1,pc\]!'
+[^:]*:144: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[r1\],pc'
+[^:]*:145: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[pc,r1\]!'
+[^:]*:146: Error: cannot use register index with PC-relative addressing -- `ldrsh r0,\[pc\],r1'
+[^:]*:149: Error: r15 not allowed here -- `ldrsht pc,\[r0\],#4'
+[^:]*:150: Error: cannot use writeback with PC-relative addressing -- `ldrsht r0,\[pc\],#4'
+[^:]*:151: Error: r15 not allowed here -- `ldrsht pc,\[r0\],r1'
+[^:]*:152: Error: cannot use register index with PC-relative addressing -- `ldrsht r0,\[pc\],r1'
+[^:]*:153: Error: cannot use register index with PC-relative addressing -- `ldrsht r0,\[r1\],pc'
+[^:]*:156: Error: r15 not allowed here -- `ldrt pc,\[r0\],#4'
+[^:]*:157: Error: cannot use register index with PC-relative addressing -- `ldrt r0,\[pc\],#4'
+[^:]*:158: Error: r15 not allowed here -- `ldrt pc,\[r0\],r1,LSL#4'
+[^:]*:159: Error: cannot use register index with PC-relative addressing -- `ldrt r0,\[pc\],r1,LSL#4'
+[^:]*:160: Error: cannot use register index with PC-relative addressing -- `ldrt r0,\[r1\],pc,LSL#4'
+[^:]*:165: Error: cannot use register index with PC-relative addressing -- `str r0,\[pc,#4\]'
+[^:]*:166: Error: cannot use register index with PC-relative addressing -- `str r0,\[pc\],#4'
+[^:]*:167: Error: cannot use register index with PC-relative addressing -- `str r0,\[pc,#4\]!'
+[^:]*:170: Error: cannot use register index with PC-relative addressing -- `str r0,\[r1,pc,LSL#4\]'
+[^:]*:171: Error: cannot use register index with PC-relative addressing -- `str r0,\[r1,pc,LSL#4\]!'
+[^:]*:172: Error: cannot use register index with PC-relative addressing -- `str r0,\[r1\],pc,LSL#4'
+[^:]*:175: Error: r15 not allowed here -- `strb pc,\[r0,#4\]'
+[^:]*:176: Error: r15 not allowed here -- `strb pc,\[r0\],#4'
+[^:]*:177: Error: r15 not allowed here -- `strb pc,\[r0,#4\]!'
+[^:]*:178: Error: cannot use register index with PC-relative addressing -- `strb r0,\[pc\],#4'
+[^:]*:179: Error: cannot use register index with PC-relative addressing -- `strb r0,\[pc,#4\]!'
+[^:]*:182: Error: r15 not allowed here -- `strb pc,\[r0,r1,LSL#4\]'
+[^:]*:183: Error: r15 not allowed here -- `strb pc,\[r0,r1,LSL#4\]!'
+[^:]*:184: Error: r15 not allowed here -- `strb pc,\[r0\],r1,LSL#4'
+[^:]*:185: Error: cannot use register index with PC-relative addressing -- `strb r1,\[r0,pc,LSL#4\]'
+[^:]*:186: Error: cannot use register index with PC-relative addressing -- `strb r1,\[r0,pc,LSL#4\]!'
+[^:]*:187: Error: cannot use register index with PC-relative addressing -- `strb r1,\[r0\],pc,LSL#4'
+[^:]*:188: Error: cannot use register index with PC-relative addressing -- `strb r0,\[pc,r1,LSL#4\]!'
+[^:]*:189: Error: cannot use register index with PC-relative addressing -- `strb r0,\[pc\],r1,LSL#4'
+[^:]*:192: Error: r15 not allowed here -- `strbt pc,\[r0\],#4'
+[^:]*:193: Error: cannot use register index with PC-relative addressing -- `strbt r0,\[pc\],#4'
+[^:]*:194: Error: r15 not allowed here -- `strbt pc,\[r0\],r1,LSL#4'
+[^:]*:195: Error: cannot use register index with PC-relative addressing -- `strbt r0,\[pc\],r1,LSL#4'
+[^:]*:196: Error: cannot use register index with PC-relative addressing -- `strbt r0,\[r1\],pc,LSL#4'
+[^:]*:199: Error: r15 not allowed here -- `strd r0,pc,\[r1,#4\]'
+[^:]*:200: Error: r15 not allowed here -- `strd r0,pc,\[r1\],#4'
+[^:]*:201: Error: r15 not allowed here -- `strd r0,pc,\[r1,#4\]!'
+[^:]*:202: Error: cannot use writeback with PC-relative addressing -- `strd r0,r1,\[pc\],#4'
+[^:]*:203: Error: cannot use writeback with PC-relative addressing -- `strd r0,r1,\[pc,#4\]!'
+[^:]*:206: Error: r15 not allowed here -- `strd r0,pc,\[r1,r2\]'
+[^:]*:207: Error: r15 not allowed here -- `strd r0,pc,\[r1,r2\]!'
+[^:]*:208: Error: r15 not allowed here -- `strd r0,pc,\[r1\],r2'
+[^:]*:209: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[r2,pc\]'
+[^:]*:210: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[r2,pc\]!'
+[^:]*:211: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[r2\],pc'
+[^:]*:212: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[pc,r2\]!'
+[^:]*:213: Error: cannot use register index with PC-relative addressing -- `strd r0,r1,\[pc\],r2'
+[^:]*:216: Error: r15 not allowed here -- `strex pc,r0,\[r1\]'
+[^:]*:217: Error: r15 not allowed here -- `strex r0,pc,\[r1\]'
+[^:]*:218: Error: instruction does not accept this addressing mode -- `strex r0,r1,\[pc\]'
+[^:]*:221: Error: r15 not allowed here -- `strexb pc,r0,\[r1\]'
+[^:]*:222: Error: r15 not allowed here -- `strexb r0,pc,\[r1\]'
+[^:]*:223: Error: instruction does not accept this addressing mode -- `strexb r0,r1,\[pc\]'
+[^:]*:226: Error: r15 not allowed here -- `strexd pc,r0,r1,\[r2\]'
+[^:]*:227: Error: r15 not allowed here -- `strexd r0,r1,r2,\[pc\]'
+[^:]*:230: Error: r15 not allowed here -- `strexh pc,r0,\[r1\]'
+[^:]*:231: Error: r15 not allowed here -- `strexh r0,pc,\[r1\]'
+[^:]*:232: Error: instruction does not accept this addressing mode -- `strexh r0,r1,\[pc\]'
+[^:]*:235: Error: r15 not allowed here -- `strh pc,\[r0,#4\]'
+[^:]*:236: Error: r15 not allowed here -- `strh pc,\[r0\],#4'
+[^:]*:237: Error: r15 not allowed here -- `strh pc,\[r0,#4\]!'
+[^:]*:238: Error: cannot use writeback with PC-relative addressing -- `strh r0,\[pc\],#4'
+[^:]*:239: Error: cannot use writeback with PC-relative addressing -- `strh r0,\[pc,#4\]!'
+[^:]*:242: Error: r15 not allowed here -- `strh pc,\[r0,r1\]'
+[^:]*:243: Error: r15 not allowed here -- `strh pc,\[r0,r1\]!'
+[^:]*:244: Error: r15 not allowed here -- `strh pc,\[r0\],r1'
+[^:]*:245: Error: cannot use register index with PC-relative addressing -- `strh r0,\[r1,pc\]'
+[^:]*:246: Error: cannot use register index with PC-relative addressing -- `strh r0,\[r1,pc\]!'
+[^:]*:247: Error: cannot use register index with PC-relative addressing -- `strh r0,\[r1\],pc'
+[^:]*:248: Error: cannot use register index with PC-relative addressing -- `strh r0,\[pc,r1\]!'
+[^:]*:249: Error: cannot use register index with PC-relative addressing -- `strh r0,\[pc\],r1'
+[^:]*:252: Error: r15 not allowed here -- `strht pc,\[r0\],#4'
+[^:]*:253: Error: cannot use writeback with PC-relative addressing -- `strht r0,\[pc\],#4'
+[^:]*:254: Error: r15 not allowed here -- `strht pc,\[r0\],r1'
+[^:]*:255: Error: cannot use register index with PC-relative addressing -- `strht r0,\[pc\],r1'
+[^:]*:256: Error: cannot use register index with PC-relative addressing -- `strht r0,\[r1\],pc'
+[^:]*:259: Error: cannot use register index with PC-relative addressing -- `strt r0,\[pc\],#4'
+[^:]*:260: Error: cannot use register index with PC-relative addressing -- `strt r0,\[pc\],r1,LSL#4'
+[^:]*:261: Error: cannot use register index with PC-relative addressing -- `strt r0,\[r1\],pc,LSL#4'
diff --git a/gas/testsuite/gas/arm/sp-pc-validations-bad.s b/gas/testsuite/gas/arm/sp-pc-validations-bad.s
new file mode 100644
index 0000000..94ecdac
--- /dev/null
+++ b/gas/testsuite/gas/arm/sp-pc-validations-bad.s
@@ -0,0 +1,266 @@
+.syntax unified
+
+@ Loads, ARM ================================================================
+.arm
+
+@ LDR (immediate, ARM)
+@ LDR (literal)
+@No unpredictable or undefined combinations.
+
+@ LDR (register)
+ldr r0,[r1,pc, LSL #2] @ Unpredictable
+ldr r0,[r1,pc, LSL #2]! @ ditto
+ldr r0,[r1],pc, LSL #2 @ ditto
+ldr r0,[pc,r1, LSL #2]! @ ditto
+ldr r0,[pc],r1, LSL #2 @ ditto
+
+@ LDRB (immediate, ARM)
+ldrb pc,[r0,#4] @ Unpredictable
+ldrb pc,[r0],#4 @ ditto
+ldrb pc,[r0,#4]! @ ditto
+
+@ LDRB (literal)
+ldrb pc, label @ Unpredictable
+ldrb pc,[pc,#-0] @ ditto
+
+@ LDRB (register)
+ldrb pc,[r0,r1, LSL #2] @ Unpredictable
+ldrb pc,[r0,r1, LSL #2]! @ ditto
+ldrb pc,[r0],r1, LSL #2 @ ditto
+ldrb r0,[r1,pc, LSL #2] @ ditto
+ldrb r0,[r1,pc, LSL #2]! @ ditto
+ldrb r0,[r1],pc, LSL #2 @ ditto
+ldrb r0,[pc,r1, LSL #2]! @ ditto
+ldrb r0,[pc],r1, LSL #2 @ ditto
+
+@ LDRBT
+ldrbt pc,[r0],#4 @ Unpredictable
+ldrbt r0,[pc],#4 @ ditto
+ldrbt pc,[r0],r1, LSL #4 @ ditto
+ldrbt r0,[pc],r1, LSL #4 @ ditto
+ldrbt r0,[r1],pc, LSL #4 @ ditto
+
+@ LDRD (immediate)
+ldrd r0,pc,[r1,#4] @ Unpredictable
+ldrd r0,pc,[r1],#4 @ ditto
+ldrd r0,pc,[r1,#4]! @ ditto
+
+@ LDRD (literal)
+ldrd r0,pc, label @ Unpredictable
+ldrd r0,pc,[PC,#-0] @ ditto
+
+@ LDRD (register)
+ldrd r0,pc,[r1,r2] @ Unpredictable
+ldrd r0,pc,[r1,r2]! @ ditto
+ldrd r0,pc,[r1],r2 @ ditto
+ldrd r0,r1,[r2,pc] @ ditto
+ldrd r0,r1,[r2,pc]! @ ditto
+ldrd r0,r1,[r2],pc @ ditto
+ldrd r0,r1,[pc,r2]! @ ditto
+ldrd r0,r1,[pc],r2 @ ditto
+
+@ LDREX
+ldrex pc,[r0] @ Unpredictable
+ldrex r0,[pc] @ ditto
+
+@ LDREXB
+ldrexb pc,[r0] @ Unpredictable
+ldrexb r0,[pc] @ ditto
+
+@ LDREXD
+ldrexd r0,r1,[pc] @ Unpredictable
+
+@ LDREXH
+ldrexh pc,[r0] @ Unpredictable
+ldrexh r0,[pc] @ ditto
+
+@ LDRH (immediate, ARM)
+ldrh pc,[r0,#4] @ Unpredictable
+ldrh pc,[r0],#4 @ ditto
+ldrh pc,[r0,#4]! @ ditto
+
+@ LDRH (literal)
+ldrh pc, label @ Unpredictable
+ldrh pc,[pc,#-0] @ ditto
+
+@ LDRH (register)
+ldrh pc,[r0,r1] @ Unpredictable
+ldrh pc,[r0,r1]! @ ditto
+ldrh pc,[r0],r1 @ ditto
+ldrh r0,[r1,pc] @ ditto
+ldrh r0,[r1,pc]! @ ditto
+ldrh r0,[r1],pc @ ditto
+ldrh r0,[pc,r1]! @ ditto
+ldrh r0,[pc],r1 @ ditto
+
+@ LDRHT
+ldrht pc, [r0], #4 @ Unpredictable
+ldrht r0, [pc], #4 @ ditto
+ldrht pc, [r0], r1 @ ditto
+ldrht r0, [pc], r1 @ ditto
+ldrht r0, [r1], pc @ ditto
+
+@ LDRSB (immediate)
+ldrsb pc,[r0,#4] @ Unpredictable
+ldrsb pc,[r0],#4 @ ditto
+ldrsb pc,[r0,#4]! @ ditto
+
+@ LDRSB (literal)
+ldrsb pc, label @ Unpredictable
+ldrsb pc,[pc,#-0] @ ditto
+
+@ LDRSB (register)
+ldrsb pc,[r0,r1] @ Unpredictable
+ldrsb pc,[r0,r1]! @ ditto
+ldrsb pc,[r0],r1 @ ditto
+ldrsb r0,[r1,pc] @ ditto
+ldrsb r0,[r1,pc]! @ ditto
+ldrsb r0,[r1],pc @ ditto
+ldrsb r0,[pc,r1]! @ ditto
+ldrsb r0,[pc],r1 @ ditto
+
+@ LDRSBT
+ldrsbt pc, [r0], #4 @ Unpredictable
+ldrsbt r0, [pc], #4 @ ditto
+ldrsbt pc, [r0], r1 @ ditto
+ldrsbt r0, [pc], r1 @ ditto
+ldrsbt r0, [r1], pc @ ditto
+
+@ LDRSH (immediate)
+ldrsh pc,[r0,#4] @ Unpredictable
+ldrsh pc,[r0],#4 @ ditto
+ldrsh pc,[r0,#4]! @ ditto
+
+@ LDRSH (literal)
+ldrsh pc, label @ Unpredictable
+ldrsh pc,[pc,#-0] @ ditto
+
+@ LDRSH (register)
+ldrsh pc,[r0,r1] @ Unpredictable
+ldrsh pc,[r0,r1]! @ ditto
+ldrsh pc,[r0],r1 @ ditto
+ldrsh r0,[r1,pc] @ ditto
+ldrsh r0,[r1,pc]! @ ditto
+ldrsh r0,[r1],pc @ ditto
+ldrsh r0,[pc,r1]! @ ditto
+ldrsh r0,[pc],r1 @ ditto
+
+@ LDRSHT
+ldrsht pc, [r0], #4 @ Unpredictable
+ldrsht r0, [pc], #4 @ ditto
+ldrsht pc, [r0], r1 @ ditto
+ldrsht r0, [pc], r1 @ ditto
+ldrsht r0, [r1], pc @ ditto
+
+@ LDRT
+ldrt pc, [r0], #4 @ Unpredictable
+ldrt r0, [pc], #4 @ ditto
+ldrt pc,[r0],r1, LSL #4 @ ditto
+ldrt r0,[pc],r1, LSL #4 @ ditto
+ldrt r0,[r1],pc, LSL #4 @ ditto
+
+@ Stores, ARM ================================================================
+
+@ STR (immediate, ARM)
+str r0,[pc,#4] @ Unpredictable
+str r0,[pc],#4 @ ditto
+str r0,[pc,#4]! @ ditto
+
+@ STR (register)
+str r0,[r1,pc, LSL #4] @ Unpredictable
+str r0,[r1,pc, LSL #4]! @ ditto
+str r0,[r1],pc, LSL #4 @ ditto
+
+@ STRB (immediate, ARM)
+strb pc,[r0,#4] @ Unpredictable
+strb pc,[r0],#4 @ ditto
+strb pc,[r0,#4]! @ ditto
+strb r0,[pc],#4 @ ditto
+strb r0,[pc,#4]! @ ditto
+
+@ STRB (register)
+strb pc,[r0,r1, LSL #4] @ Unpredictable
+strb pc,[r0,r1, LSL #4]! @ ditto
+strb pc,[r0],r1, LSL #4 @ ditto
+strb r1,[r0,pc, LSL #4] @ ditto
+strb r1,[r0,pc, LSL #4]! @ ditto
+strb r1,[r0],pc, LSL #4 @ ditto
+strb r0,[pc,r1, LSL #4]! @ ditto
+strb r0,[pc],r1, LSL #4 @ ditto
+
+@ STRBT
+strbt pc,[r0],#4 @ Unpredictable
+strbt r0,[pc],#4 @ ditto
+strbt pc,[r0],r1, LSL #4 @ ditto
+strbt r0,[pc],r1, LSL #4 @ ditto
+strbt r0,[r1],pc, LSL #4 @ ditto
+
+@ STRD (immediate)
+strd r0,pc,[r1,#4] @ ditto
+strd r0,pc,[r1],#4 @ ditto
+strd r0,pc,[r1,#4]! @ ditto
+strd r0,r1,[pc],#4 @ ditto
+strd r0,r1,[pc,#4]! @ ditto
+
+@STRD (register)
+strd r0,pc,[r1,r2] @ Unpredictable
+strd r0,pc,[r1,r2]! @ ditto
+strd r0,pc,[r1],r2 @ ditto
+strd r0,r1,[r2,pc] @ ditto
+strd r0,r1,[r2,pc]! @ ditto
+strd r0,r1,[r2],pc @ ditto
+strd r0,r1,[pc,r2]! @ ditto
+strd r0,r1,[pc],r2 @ ditto
+
+@ STREX
+strex pc,r0,[r1] @ Unpredictable
+strex r0,pc,[r1] @ ditto
+strex r0,r1,[pc] @ ditto
+
+@ STREXB
+strexb pc,r0,[r1] @ Unpredictable
+strexb r0,pc,[r1] @ ditto
+strexb r0,r1,[pc] @ ditto
+
+@ STREXD
+strexd pc,r0,r1,[r2] @ Unpredictable
+strexd r0,r1,r2,[pc] @ ditto
+
+@ STREXH
+strexh pc,r0,[r1] @ Unpredictable
+strexh r0,pc,[r1] @ ditto
+strexh r0,r1,[pc] @ ditto
+
+@ STRH (immediate, ARM)
+strh pc,[r0,#4] @ Unpredictable
+strh pc,[r0],#4 @ ditto
+strh pc,[r0,#4]! @ ditto
+strh r0,[pc],#4 @ ditto
+strh r0,[pc,#4]! @ ditto
+
+@ STRH (register)
+strh pc,[r0,r1] @ Unpredictable
+strh pc,[r0,r1]! @ ditto
+strh pc,[r0],r1 @ ditto
+strh r0,[r1,pc] @ ditto
+strh r0,[r1,pc]! @ ditto
+strh r0,[r1],pc @ ditto
+strh r0,[pc,r1]! @ ditto
+strh r0,[pc],r1 @ ditto
+
+@ STRHT
+strht pc, [r0], #4 @ Unpredictable
+strht r0, [pc], #4 @ ditto
+strht pc, [r0], r1 @ ditto
+strht r0, [pc], r1 @ ditto
+strht r0, [r1], pc @ ditto
+
+@ STRT
+strt r0, [pc], #4 @ Unpredictable
+strt r0, [pc],r1, LSL #4 @ ditto
+strt r0, [r1],pc, LSL #4 @ ditto
+
+@ ============================================================================
+
+.label:
+ldr r0, [r1]
diff --git a/gas/testsuite/gas/arm/thumb2_bcond.d b/gas/testsuite/gas/arm/thumb2_bcond.d
index 02903a9..96f6903 100644
--- a/gas/testsuite/gas/arm/thumb2_bcond.d
+++ b/gas/testsuite/gas/arm/thumb2_bcond.d
@@ -18,8 +18,10 @@ Disassembly of section .text:
0+01a <[^>]+> e8d4 f001 tbbgt \[r4, r1\]
0+01e <[^>]+> bfb8 it lt
0+020 <[^>]+> df00 svclt 0
-0+022 <[^>]+> bfdc itt le
-0+024 <[^>]+> be00 bkpt 0x0000
-0+026 <[^>]+> bf00 nople
-0+028 <[^>]+> bf00 nop
-0+02a <[^>]+> bf00 nop
+0+022 <[^>]+> bf08 it eq
+0+024 <[^>]+> f8d0 f000 ldreq.w pc, \[r0\]
+0+028 <[^>]+> bfdc itt le
+0+02a <[^>]+> be00 bkpt 0x0000
+0+02c <[^>]+> bf00 nople
+0+02e <[^>]+> bf00 nop
+0+030 <[^>]+> bf00 nop
diff --git a/gas/testsuite/gas/arm/thumb2_bcond.s b/gas/testsuite/gas/arm/thumb2_bcond.s
index 4a066f2..aef6e8f 100644
--- a/gas/testsuite/gas/arm/thumb2_bcond.s
+++ b/gas/testsuite/gas/arm/thumb2_bcond.s
@@ -18,6 +18,8 @@ thumb2_bcond:
tbbgt [r4, r1]
it lt
svclt 0
+ it eq
+ ldreq pc, [r0]
itt le
bkpt #0
nople
diff --git a/gas/testsuite/gas/arm/unpredictable.d b/gas/testsuite/gas/arm/unpredictable.d
index 8cba074..e78727a 100644
--- a/gas/testsuite/gas/arm/unpredictable.d
+++ b/gas/testsuite/gas/arm/unpredictable.d
@@ -70,7 +70,5 @@ Disassembly of section .text:
0+0fc <[^>]+> [^<]+<UNPREDICTABLE>
0+100 <[^>]+> [^<]+<UNPREDICTABLE>
0+104 <[^>]+> [^<]+<UNPREDICTABLE>
-0+108 <[^>]+> [^<]+<UNPREDICTABLE>
-0+10c <[^>]+> [^<]+<UNPREDICTABLE>
-0+110 <[^>]+> e1a00000[ ]+nop[ ]+; \(mov r0, r0\)
+0+108 <[^>]+> e1a00000[ ]+nop[ ]+; \(mov r0, r0\)
#pass
diff --git a/gas/testsuite/gas/arm/unpredictable.s b/gas/testsuite/gas/arm/unpredictable.s
index 7849676..5fab0a4 100644
--- a/gas/testsuite/gas/arm/unpredictable.s
+++ b/gas/testsuite/gas/arm/unpredictable.s
@@ -55,8 +55,6 @@ unpredictable:
.word 0xe92f0010 @ stmdb r15!, { r4 }
.word 0xe82f0020 @ stmda r15!, { r5 }
- strb pc, [r0, r1]
- strbt pc, [r0], r1
.word 0xe180f0b1 @ strh pc, [r0, r1]
.word 0xe103f092 @ swp r15, r2, [r3]