From: Richard Sandiford Date: Wed, 21 Sep 2016 15:51:09 +0000 (+0100) Subject: [AArch64][SVE 14/32] Make aarch64_logical_immediate_p take an element size X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=42408347b86745fdbd4bec9ee3a6a3fee31c4dee;p=binutils-gdb.git [AArch64][SVE 14/32] Make aarch64_logical_immediate_p take an element size SVE supports logical immediate operations on 8-bit, 16-bit and 32-bit elements, treating them as aliases of operations on 64-bit elements in which the immediate is replicated. This patch therefore replaces the "32-bit/64-bit" input to aarch64_logical_immediate_p with a more general "number of bytes" input. opcodes/ * aarch64-opc.c (aarch64_logical_immediate_p): Replace is32 with an esize parameter. (operand_general_constraint_met_p): Update accordingly. Fix misindented code. * aarch64-asm.c (aarch64_ins_limm): Update call to aarch64_logical_immediate_p. --- diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index c12ea3a9d4d..9f44e978be4 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,12 @@ +2016-09-21 Richard Sandiford + + * aarch64-opc.c (aarch64_logical_immediate_p): Replace is32 + with an esize parameter. + (operand_general_constraint_met_p): Update accordingly. + Fix misindented code. + * aarch64-asm.c (aarch64_ins_limm): Update call to + aarch64_logical_immediate_p. + 2016-09-21 Richard Sandiford * aarch64-opc.c (match_operands_qualifier): Handle F_STRICT. diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c index 2430be5438b..8fbd66f7e0e 100644 --- a/opcodes/aarch64-asm.c +++ b/opcodes/aarch64-asm.c @@ -436,11 +436,11 @@ aarch64_ins_limm (const aarch64_operand *self, const aarch64_opnd_info *info, { aarch64_insn value; uint64_t imm = info->imm.value; - int is32 = aarch64_get_qualifier_esize (inst->operands[0].qualifier) == 4; + int esize = aarch64_get_qualifier_esize (inst->operands[0].qualifier); if (inst->opcode->op == OP_BIC) imm = ~imm; - if (aarch64_logical_immediate_p (imm, is32, &value) == FALSE) + if (aarch64_logical_immediate_p (imm, esize, &value) == FALSE) /* The constraint check should have guaranteed this wouldn't happen. */ assert (0); diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index d870fd6203c..84da821f13e 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -1062,16 +1062,18 @@ build_immediate_table (void) be accepted by logical (immediate) instructions e.g. ORR , , #. - IS32 indicates whether or not VALUE is a 32-bit immediate. + ESIZE is the number of bytes in the decoded immediate value. If ENCODING is not NULL, on the return of TRUE, the standard encoding for VALUE will be returned in *ENCODING. */ bfd_boolean -aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding) +aarch64_logical_immediate_p (uint64_t value, int esize, aarch64_insn *encoding) { simd_imm_encoding imm_enc; const simd_imm_encoding *imm_encoding; static bfd_boolean initialized = FALSE; + uint64_t upper; + int i; DEBUG_TRACE ("enter with 0x%" PRIx64 "(%" PRIi64 "), is32: %d", value, value, is32); @@ -1082,17 +1084,16 @@ aarch64_logical_immediate_p (uint64_t value, int is32, aarch64_insn *encoding) initialized = TRUE; } - if (is32) - { - /* Allow all zeros or all ones in top 32-bits, so that - constant expressions like ~1 are permitted. */ - if (value >> 32 != 0 && value >> 32 != 0xffffffff) - return FALSE; + /* Allow all zeros or all ones in top bits, so that + constant expressions like ~1 are permitted. */ + upper = (uint64_t) -1 << (esize * 4) << (esize * 4); + if ((value & ~upper) != value && (value | upper) != value) + return FALSE; - /* Replicate the 32 lower bits to the 32 upper bits. */ - value &= 0xffffffff; - value |= value << 32; - } + /* Replicate to a full 64-bit value. */ + value &= ~upper; + for (i = esize * 8; i < 64; i *= 2) + value |= (value << i); imm_enc.imm = value; imm_encoding = (const simd_imm_encoding *) @@ -1645,7 +1646,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, case AARCH64_OPND_IMM_MOV: { - int is32 = aarch64_get_qualifier_esize (opnds[0].qualifier) == 4; + int esize = aarch64_get_qualifier_esize (opnds[0].qualifier); imm = opnd->imm.value; assert (idx == 1); switch (opcode->op) @@ -1654,7 +1655,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, imm = ~imm; /* Fall through... */ case OP_MOV_IMM_WIDE: - if (!aarch64_wide_constant_p (imm, is32, NULL)) + if (!aarch64_wide_constant_p (imm, esize == 4, NULL)) { set_other_error (mismatch_detail, idx, _("immediate out of range")); @@ -1662,7 +1663,7 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, } break; case OP_MOV_IMM_LOG: - if (!aarch64_logical_immediate_p (imm, is32, NULL)) + if (!aarch64_logical_immediate_p (imm, esize, NULL)) { set_other_error (mismatch_detail, idx, _("immediate out of range")); @@ -1707,18 +1708,18 @@ operand_general_constraint_met_p (const aarch64_opnd_info *opnds, int idx, break; case AARCH64_OPND_LIMM: - { - int is32 = opnds[0].qualifier == AARCH64_OPND_QLF_W; - uint64_t uimm = opnd->imm.value; - if (opcode->op == OP_BIC) - uimm = ~uimm; - if (aarch64_logical_immediate_p (uimm, is32, NULL) == FALSE) - { - set_other_error (mismatch_detail, idx, - _("immediate out of range")); - return 0; - } - } + { + int esize = aarch64_get_qualifier_esize (opnds[0].qualifier); + uint64_t uimm = opnd->imm.value; + if (opcode->op == OP_BIC) + uimm = ~uimm; + if (aarch64_logical_immediate_p (uimm, esize, NULL) == FALSE) + { + set_other_error (mismatch_detail, idx, + _("immediate out of range")); + return 0; + } + } break; case AARCH64_OPND_IMM0: