From d685192a58d4c198633bd0e69cfe0a114576e98a Mon Sep 17 00:00:00 2001 From: Matthew Wahab Date: Fri, 27 Nov 2015 15:25:08 +0000 Subject: [AArch64] Add ARMv8.2 instructions BFC and REV64. ARMv8.2 adds two new instructions: BFC as an alias for BFM and REV64 as an alias for REV. This patch set adds support for these to binutils, enabled when the -march=armv8.2-a is given. It depends on the support for an instruction being its preferred form which was added in an earlier patch. This patch adds the alias BFC , #, # as the preferred form for BFM when the source is a zero register and the conditions for using the BFI form are met (in other words, BFC is the preferred form for BFI , , #, # when the is a zero register). gas/testsuite/ 2015-11-27 Matthew Wahab * gas/aarch64/alias-2.d: New. * gas/aarch64/alias-2.s: New. include/opcode/ 2015-11-27 Matthew Wahab * aarch64.h (aarch64_op): Add OP_BFC. opcodes/ 2015-11-27 Matthew Wahab * aarch64-asm-2.c: Regenerate. * aarch64-asm.c (convert_bfc_to_bfm): New. (convert_to_real): Add case for OP_BFC. * aarch64-dis-2.c: Regenerate. * aarch64-dis.c: (convert_bfm_to_bfc): New. (convert_to_alias): Add case for OP_BFC. * aarch64-opc-2.c: Regenerate. * aarch64-opc.c (operand_general_constraint_met_p): Weaken assert to allow width operand in three-operand instructions. * aarch64-tbl.h (QL_BF1): New. (aarch64_feature_v8_2): New. (ARMV8_2): New. (aarch64_opcode_table): Add "bfc". Change-Id: I6efe318b2538ba11f0caece7c6d70957441c872b --- opcodes/aarch64-dis.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'opcodes/aarch64-dis.c') diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index d744c25..efa1074 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -1601,6 +1601,45 @@ convert_bfm_to_bfi (aarch64_inst *inst) } /* The instruction written: + BFC , #, # + is equivalent to: + BFM , XZR, #((64-)&0x3f), #(-1). */ + +static int +convert_bfm_to_bfc (aarch64_inst *inst) +{ + int64_t immr, imms, val; + + /* Should have been assured by the base opcode value. */ + assert (inst->operands[1].reg.regno == 0x1f); + + immr = inst->operands[2].imm.value; + imms = inst->operands[3].imm.value; + val = inst->operands[2].qualifier == AARCH64_OPND_QLF_imm_0_31 ? 32 : 64; + if (imms < immr) + { + /* Drop XZR from the second operand. */ + copy_operand_info (inst, 1, 2); + copy_operand_info (inst, 2, 3); + inst->operands[3].type = AARCH64_OPND_NIL; + + /* Recalculate the immediates. */ + inst->operands[1].imm.value = (val - immr) & (val - 1); + inst->operands[2].imm.value = imms + 1; + + /* The two opcodes have different qualifiers for the operands; reset to + help the checking. */ + reset_operand_qualifier (inst, 1); + reset_operand_qualifier (inst, 2); + reset_operand_qualifier (inst, 3); + + return 1; + } + + return 0; +} + +/* The instruction written: LSL , , # is equivalent to: UBFM , , #((64-)&0x3f), #(63-). */ @@ -1759,6 +1798,8 @@ convert_to_alias (aarch64_inst *inst, const aarch64_opcode *alias) case OP_BFI: case OP_UBFIZ: return convert_bfm_to_bfi (inst); + case OP_BFC: + return convert_bfm_to_bfc (inst); case OP_MOV_V: return convert_orr_to_mov (inst); case OP_MOV_IMM_WIDE: -- cgit v1.1