static inline bfd_reloc_code_real_type
ldst_lo12_determine_real_reloc_type (void)
{
- unsigned logsz, max_logsz;
- enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
- enum aarch64_opnd_qualifier opd1_qlf = inst.base.operands[1].qualifier;
-
const bfd_reloc_code_real_type reloc_ldst_lo12[5][5] = {
{
BFD_RELOC_AARCH64_LDST8_LO12,
== BFD_RELOC_AARCH64_TLSLE_LDST_TPREL_LO12_NC));
gas_assert (inst.base.opcode->operands[1] == AARCH64_OPND_ADDR_UIMM12);
- if (opd1_qlf == AARCH64_OPND_QLF_NIL)
- opd1_qlf =
- aarch64_get_expected_qualifier (inst.base.opcode->qualifiers_list,
- 1, opd0_qlf, 0);
- gas_assert (opd1_qlf != AARCH64_OPND_QLF_NIL);
+ enum aarch64_opnd_qualifier opd0_qlf = inst.base.operands[0].qualifier;
+ enum aarch64_opnd_qualifier opd1_qlf = AARCH64_OPND_QLF_NIL;
+ const aarch64_opnd_qualifier_seq_t *qseq_list
+ = inst.base.opcode->qualifiers_list;
+ for (int i = 0; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
+ if (qseq_list[i][0] == opd0_qlf)
+ {
+ opd1_qlf = qseq_list[i][1];
+ break;
+ }
+
+ unsigned logsz = 0;
+ unsigned max_logsz;
- logsz = get_log2 (aarch64_get_qualifier_esize (opd1_qlf));
+ if (opd1_qlf >= AARCH64_OPND_QLF_S_B && opd1_qlf <= AARCH64_OPND_QLF_S_Q)
+ logsz = opd1_qlf - AARCH64_OPND_QLF_S_B;
if (inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12
|| inst.reloc.type == BFD_RELOC_AARCH64_TLSLD_LDST_DTPREL_LO12_NC
--- /dev/null
+#as: -march=armv8-a
+#error_output: reloc-invalid-qualifiers.l
--- /dev/null
+[^ :]+: Assembler messages:
+[^ :]+:[0-9]+: Error: operand mismatch -- `ldrb x0,\[x0,#:lo12:label\]'
+[^ :]+:[0-9]+: Info: did you mean this\?
+[^ :]+:[0-9]+: Info: ldrb w0, \[x0\]
--- /dev/null
+
+label:
+# Test error handling for an incorrect register size
+ ldrb x0, [x0, #:lo12:label]
extern int
aarch64_operand_index (const enum aarch64_opnd *, enum aarch64_opnd);
-extern aarch64_opnd_qualifier_t
-aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *, int,
- const aarch64_opnd_qualifier_t, int);
-
extern bool
aarch64_is_destructive_by_operands (const aarch64_opcode *);
&& operand->reg.regno == 31);
}
-/* Given qualifier sequence list QSEQ_LIST and the known qualifier KNOWN_QLF
- for operand KNOWN_IDX, return the expected qualifier for operand IDX.
-
- Return NIL if more than one expected qualifiers are found. */
-
-aarch64_opnd_qualifier_t
-aarch64_get_expected_qualifier (const aarch64_opnd_qualifier_seq_t *qseq_list,
- int idx,
- const aarch64_opnd_qualifier_t known_qlf,
- int known_idx)
-{
- int i, saved_i;
-
- /* Special case.
-
- When the known qualifier is NIL, we have to assume that there is only
- one qualifier sequence in the *QSEQ_LIST and return the corresponding
- qualifier directly. One scenario is that for instruction
- PRFM <prfop>, [<Xn|SP>, #:lo12:<symbol>]
- which has only one possible valid qualifier sequence
- NIL, S_D
- the caller may pass NIL in KNOWN_QLF to obtain S_D so that it can
- determine the correct relocation type (i.e. LDST64_LO12) for PRFM.
-
- Because the qualifier NIL has dual roles in the qualifier sequence:
- it can mean no qualifier for the operand, or the qualifer sequence is
- not in use (when all qualifiers in the sequence are NILs), we have to
- handle this special case here. */
- if (known_qlf == AARCH64_OPND_QLF_NIL)
- {
- assert (qseq_list[0][known_idx] == AARCH64_OPND_QLF_NIL);
- return qseq_list[0][idx];
- }
-
- for (i = 0, saved_i = -1; i < AARCH64_MAX_QLF_SEQ_NUM; ++i)
- {
- if (qseq_list[i][known_idx] == known_qlf)
- {
- if (saved_i != -1)
- /* More than one sequences are found to have KNOWN_QLF at
- KNOWN_IDX. */
- return AARCH64_OPND_QLF_NIL;
- saved_i = i;
- }
- }
-
- return qseq_list[saved_i][idx];
-}
-
enum operand_qualifier_kind
{
OQK_NIL,