+/* Check for loads and stores that will cause unpredictable behavior. */
+
+static void
+warn_unpredictable_ldst (aarch64_instruction *instr, char *str)
+{
+ aarch64_inst *base = &instr->base;
+ const aarch64_opcode *opcode = base->opcode;
+ const aarch64_opnd_info *opnds = base->operands;
+ switch (opcode->iclass)
+ {
+ case ldst_pos:
+ case ldst_imm9:
+ case ldst_unscaled:
+ case ldst_unpriv:
+ /* Loading/storing the base register is unpredictable if writeback. */
+ if ((aarch64_get_operand_class (opnds[0].type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && opnds[0].reg.regno == opnds[1].addr.base_regno
+ && opnds[1].addr.base_regno != REG_SP
+ && opnds[1].addr.writeback)
+ as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
+ break;
+ case ldstpair_off:
+ case ldstnapair_offs:
+ case ldstpair_indexed:
+ /* Loading/storing the base register is unpredictable if writeback. */
+ if ((aarch64_get_operand_class (opnds[0].type)
+ == AARCH64_OPND_CLASS_INT_REG)
+ && (opnds[0].reg.regno == opnds[2].addr.base_regno
+ || opnds[1].reg.regno == opnds[2].addr.base_regno)
+ && opnds[2].addr.base_regno != REG_SP
+ && opnds[2].addr.writeback)
+ as_warn (_("unpredictable transfer with writeback -- `%s'"), str);
+ /* Load operations must load different registers. */
+ if ((opcode->opcode & (1 << 22))
+ && opnds[0].reg.regno == opnds[1].reg.regno)
+ as_warn (_("unpredictable load of register pair -- `%s'"), str);
+ break;
+ default:
+ break;
+ }
+}
+