diff options
-rw-r--r-- | gas/ChangeLog | 5 | ||||
-rw-r--r-- | gas/config/tc-aarch64.c | 5 | ||||
-rw-r--r-- | include/ChangeLog | 5 | ||||
-rw-r--r-- | include/opcode/aarch64.h | 9 | ||||
-rw-r--r-- | opcodes/ChangeLog | 8 | ||||
-rw-r--r-- | opcodes/aarch64-opc.c | 17 | ||||
-rw-r--r-- | opcodes/aarch64-tbl.h | 32 |
7 files changed, 65 insertions, 16 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog index ac9d359..425c37a 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,5 +1,10 @@ 2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * config/tc-aarch64.c (output_operand_error_record): Handle + AARCH64_OPDE_UNTIED_OPERAND. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * config/tc-aarch64.c (find_best_match): Simplify, allowing an instruction with all-NIL qualifiers to fail to match. diff --git a/gas/config/tc-aarch64.c b/gas/config/tc-aarch64.c index f50de70..8335230 100644 --- a/gas/config/tc-aarch64.c +++ b/gas/config/tc-aarch64.c @@ -4371,6 +4371,11 @@ output_operand_error_record (const operand_error_record *record, char *str) } break; + case AARCH64_OPDE_UNTIED_OPERAND: + as_bad (_("operand %d must be the same register as operand 1 -- `%s'"), + detail->index + 1, str); + break; + case AARCH64_OPDE_OUT_OF_RANGE: if (detail->data[0] != detail->data[1]) as_bad (_("%s out of range %d to %d at operand %d -- `%s'"), diff --git a/include/ChangeLog b/include/ChangeLog index 21ddbfd..e6c3dbd 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,5 +1,10 @@ 2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * opcode/aarch64.h (aarch64_opcode): Add a tied_operand field. + (AARCH64_OPDE_UNTIED_OPERAND): New aarch64_operand_error_kind. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * opcode/aarch64.h (F_STRICT): New flag. 2016-09-07 Richard Earnshaw <rearnsha@arm.com> diff --git a/include/opcode/aarch64.h b/include/opcode/aarch64.h index 24a2ddb..d39f10d 100644 --- a/include/opcode/aarch64.h +++ b/include/opcode/aarch64.h @@ -539,6 +539,10 @@ struct aarch64_opcode /* Flags providing information about this instruction */ uint32_t flags; + /* If nonzero, this operand and operand 0 are both registers and + are required to have the same register number. */ + unsigned char tied_operand; + /* If non-NULL, a function to verify that a given instruction is valid. */ bfd_boolean (* verifier) (const struct aarch64_opcode *, const aarch64_insn); }; @@ -872,6 +876,10 @@ typedef struct aarch64_inst aarch64_inst; No syntax error, but the operands are not a valid combination, e.g. FMOV D0,S0 + AARCH64_OPDE_UNTIED_OPERAND + The asm failed to use the same register for a destination operand + and a tied source operand. + AARCH64_OPDE_OUT_OF_RANGE Error about some immediate value out of a valid range. @@ -908,6 +916,7 @@ enum aarch64_operand_error_kind AARCH64_OPDE_SYNTAX_ERROR, AARCH64_OPDE_FATAL_SYNTAX_ERROR, AARCH64_OPDE_INVALID_VARIANT, + AARCH64_OPDE_UNTIED_OPERAND, AARCH64_OPDE_OUT_OF_RANGE, AARCH64_OPDE_UNALIGNED, AARCH64_OPDE_REG_LIST, diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index eab6811..925ea1e 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,5 +1,13 @@ 2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * aarch64-tbl.h (CORE_INSN, __FP_INSN, SIMD_INSN, CRYP_INSN) + (_CRC_INSN, _LSE_INSN, _LOR_INSN, RDMA_INSN, FP16_INSN, SF16_INSN) + (V8_2_INSN, aarch64_opcode_table): Initialize tied_operand field. + * aarch64-opc.c (aarch64_match_operands_constraint): Check for + tied operands. + +2016-09-21 Richard Sandiford <richard.sandiford@arm.com> + * aarch64-opc.c (get_offset_int_reg_name): New function. (print_immediate_offset_address): Likewise. (print_register_offset_address): Take the base and offset diff --git a/opcodes/aarch64-opc.c b/opcodes/aarch64-opc.c index 7a73c7e..30501fc 100644 --- a/opcodes/aarch64-opc.c +++ b/opcodes/aarch64-opc.c @@ -2058,6 +2058,23 @@ aarch64_match_operands_constraint (aarch64_inst *inst, DEBUG_TRACE ("enter"); + /* Check for cases where a source register needs to be the same as the + destination register. Do this before matching qualifiers since if + an instruction has both invalid tying and invalid qualifiers, + the error about qualifiers would suggest several alternative + instructions that also have invalid tying. */ + i = inst->opcode->tied_operand; + if (i > 0 && (inst->operands[0].reg.regno != inst->operands[i].reg.regno)) + { + if (mismatch_detail) + { + mismatch_detail->kind = AARCH64_OPDE_UNTIED_OPERAND; + mismatch_detail->index = i; + mismatch_detail->error = NULL; + } + return 0; + } + /* Match operands' qualifier. *INST has already had qualifier establish for some, if not all, of its operands; we need to find out whether these established diff --git a/opcodes/aarch64-tbl.h b/opcodes/aarch64-tbl.h index 9a831e4..8f1c9b2 100644 --- a/opcodes/aarch64-tbl.h +++ b/opcodes/aarch64-tbl.h @@ -1393,27 +1393,27 @@ static const aarch64_feature_set aarch64_feature_stat_profile = #define ARMV8_2 &aarch64_feature_v8_2 #define CORE_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, OP, CORE, OPS, QUALS, FLAGS, 0, NULL } #define __FP_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, OP, FP, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, OP, FP, OPS, QUALS, FLAGS, 0, NULL } #define SIMD_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, OP, SIMD, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, OP, SIMD, OPS, QUALS, FLAGS, 0, NULL } #define CRYP_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, CRYPTO, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, CRYPTO, OPS, QUALS, FLAGS, 0, NULL } #define _CRC_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, CRC, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, CRC, OPS, QUALS, FLAGS, 0, NULL } #define _LSE_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, LSE, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, LSE, OPS, QUALS, FLAGS, 0, NULL } #define _LOR_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, LOR, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, LOR, OPS, QUALS, FLAGS, 0, NULL } #define RDMA_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, RDMA, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, RDMA, OPS, QUALS, FLAGS, 0, NULL } #define FF16_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, FP_F16, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, FP_F16, OPS, QUALS, FLAGS, 0, NULL } #define SF16_INSN(NAME,OPCODE,MASK,CLASS,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, 0, SIMD_F16, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, 0, SIMD_F16, OPS, QUALS, FLAGS, 0, NULL } #define V8_2_INSN(NAME,OPCODE,MASK,CLASS,OP,OPS,QUALS,FLAGS) \ - { NAME, OPCODE, MASK, CLASS, OP, ARMV8_2, OPS, QUALS, FLAGS, NULL } + { NAME, OPCODE, MASK, CLASS, OP, ARMV8_2, OPS, QUALS, FLAGS, 0, NULL } struct aarch64_opcode aarch64_opcode_table[] = { @@ -2389,13 +2389,13 @@ struct aarch64_opcode aarch64_opcode_table[] = CORE_INSN ("ldp", 0x29400000, 0x7ec00000, ldstpair_off, 0, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF), CORE_INSN ("stp", 0x2d000000, 0x3fc00000, ldstpair_off, 0, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0), CORE_INSN ("ldp", 0x2d400000, 0x3fc00000, ldstpair_off, 0, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0), - {"ldpsw", 0x69400000, 0xffc00000, ldstpair_off, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0, VERIFIER (ldpsw)}, + {"ldpsw", 0x69400000, 0xffc00000, ldstpair_off, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0, 0, VERIFIER (ldpsw)}, /* Load/store register pair (indexed). */ CORE_INSN ("stp", 0x28800000, 0x7ec00000, ldstpair_indexed, 0, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF), CORE_INSN ("ldp", 0x28c00000, 0x7ec00000, ldstpair_indexed, 0, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_R, F_SF), CORE_INSN ("stp", 0x2c800000, 0x3ec00000, ldstpair_indexed, 0, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0), CORE_INSN ("ldp", 0x2cc00000, 0x3ec00000, ldstpair_indexed, 0, OP3 (Ft, Ft2, ADDR_SIMM7), QL_LDST_PAIR_FP, 0), - {"ldpsw", 0x68c00000, 0xfec00000, ldstpair_indexed, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0, VERIFIER (ldpsw)}, + {"ldpsw", 0x68c00000, 0xfec00000, ldstpair_indexed, 0, CORE, OP3 (Rt, Rt2, ADDR_SIMM7), QL_LDST_PAIR_X32, 0, 0, VERIFIER (ldpsw)}, /* Load register (literal). */ CORE_INSN ("ldr", 0x18000000, 0xbf000000, loadlit, OP_LDR_LIT, OP2 (Rt, ADDR_PCREL19), QL_R_PCREL, F_GPRSIZE_IN_Q), CORE_INSN ("ldr", 0x1c000000, 0x3f000000, loadlit, OP_LDRV_LIT, OP2 (Ft, ADDR_PCREL19), QL_FP_PCREL, 0), @@ -2613,8 +2613,8 @@ struct aarch64_opcode aarch64_opcode_table[] = CORE_INSN ("wfi", 0xd503207f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS), CORE_INSN ("sev", 0xd503209f, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS), CORE_INSN ("sevl",0xd50320bf, 0xffffffff, ic_system, 0, OP0 (), {}, F_ALIAS), - {"esb", 0xd503221f, 0xffffffff, ic_system, 0, RAS, OP0 (), {}, F_ALIAS, NULL}, - {"psb", 0xd503223f, 0xffffffff, ic_system, 0, STAT_PROFILE, OP1 (BARRIER_PSB), {}, F_ALIAS, NULL}, + {"esb", 0xd503221f, 0xffffffff, ic_system, 0, RAS, OP0 (), {}, F_ALIAS, 0, NULL}, + {"psb", 0xd503223f, 0xffffffff, ic_system, 0, STAT_PROFILE, OP1 (BARRIER_PSB), {}, F_ALIAS, 0, NULL}, CORE_INSN ("clrex", 0xd503305f, 0xfffff0ff, ic_system, 0, OP1 (UIMM4), {}, F_OPD0_OPT | F_DEFAULT (0xF)), CORE_INSN ("dsb", 0xd503309f, 0xfffff0ff, ic_system, 0, OP1 (BARRIER), {}, 0), CORE_INSN ("dmb", 0xd50330bf, 0xfffff0ff, ic_system, 0, OP1 (BARRIER), {}, 0), @@ -2648,7 +2648,7 @@ struct aarch64_opcode aarch64_opcode_table[] = CORE_INSN ("bgt", 0x5400000c, 0xff00001f, condbranch, 0, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO), CORE_INSN ("ble", 0x5400000d, 0xff00001f, condbranch, 0, OP1 (ADDR_PCREL19), QL_PCREL_NIL, F_ALIAS | F_PSEUDO), - {0, 0, 0, 0, 0, 0, {}, {}, 0, NULL}, + {0, 0, 0, 0, 0, 0, {}, {}, 0, 0, NULL}, }; #ifdef AARCH64_OPERANDS |