X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=opcodes%2Faarch64-dis.c;h=aa38adb9020eb916515a1154aa5270db1f090830;hb=00c2093f698e8f40c04340cb1832d09e11ece237;hp=d8c5fa7aa5ca86fd477579c72b054f5c6ed946e0;hpb=1a0670f37442b7ae904932b347353046126b990c;p=deliverable%2Fbinutils-gdb.git diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c index d8c5fa7aa5..aa38adb902 100644 --- a/opcodes/aarch64-dis.c +++ b/opcodes/aarch64-dis.c @@ -1,5 +1,5 @@ /* aarch64-dis.c -- AArch64 disassembler. - Copyright (C) 2009-2016 Free Software Foundation, Inc. + Copyright (C) 2009-2017 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of the GNU opcodes library. @@ -20,7 +20,7 @@ #include "sysdep.h" #include "bfd_stdint.h" -#include "dis-asm.h" +#include "disassemble.h" #include "libiberty.h" #include "opintl.h" #include "aarch64-dis.h" @@ -325,6 +325,26 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, info->reglane.index = (unsigned) (value >> 1); } } + else if (inst->opcode->iclass == dotproduct) + { + /* Need information in other operand(s) to help decoding. */ + info->qualifier = get_expected_qualifier (inst, info->idx); + switch (info->qualifier) + { + case AARCH64_OPND_QLF_S_4B: + /* L:H */ + info->reglane.index = extract_fields (code, 0, 2, FLD_H, FLD_L); + info->reglane.regno &= 0x1f; + break; + default: + return 0; + } + } + else if (inst->opcode->iclass == cryptosm3) + { + /* index for e.g. SM3TT2A .4S, .4S, S[]. */ + info->reglane.index = extract_field (FLD_SM3_imm2, code, 0); + } else { /* Index only for e.g. SQDMLAL , , .[] @@ -351,6 +371,14 @@ aarch64_ext_reglane (const aarch64_operand *self, aarch64_opnd_info *info, default: return 0; } + + if (inst->opcode->op == OP_FCMLA_ELEM) + { + /* Complex operand takes two elements. */ + if (info->reglane.index & 1) + return 0; + info->reglane.index /= 2; + } } return 1; @@ -401,6 +429,9 @@ aarch64_ext_ldst_reglist (const aarch64_operand *self ATTRIBUTE_UNUSED, info->reglist.first_regno = extract_field (FLD_Rt, code, 0); /* opcode */ value = extract_field (FLD_opcode, code, 0); + /* PR 21595: Check for a bogus value. */ + if (value >= ARRAY_SIZE (data)) + return 0; if (expected_num != data[value].num_elements || data[value].is_reserved) return 0; info->reglist.num_regs = data[value].num_regs; @@ -703,6 +734,30 @@ aarch64_ext_fpimm (const aarch64_operand *self, aarch64_opnd_info *info, return 1; } +/* Decode a 1-bit rotate immediate (#90 or #270). */ +int +aarch64_ext_imm_rotate1 (const aarch64_operand *self, aarch64_opnd_info *info, + const aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + uint64_t rot = extract_field (self->fields[0], code, 0); + assert (rot < 2U); + info->imm.value = rot * 180 + 90; + return 1; +} + +/* Decode a 2-bit rotate immediate (#0, #90, #180 or #270). */ +int +aarch64_ext_imm_rotate2 (const aarch64_operand *self, aarch64_opnd_info *info, + const aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + uint64_t rot = extract_field (self->fields[0], code, 0); + assert (rot < 4U); + info->imm.value = rot * 90; + return 1; +} + /* Decode scale for e.g. SCVTF
, , #. */ int aarch64_ext_fbits (const aarch64_operand *self ATTRIBUTE_UNUSED, @@ -886,6 +941,28 @@ aarch64_ext_addr_simple (const aarch64_operand *self ATTRIBUTE_UNUSED, return 1; } +/* Decode the address operand for e.g. + stlur , [{, }]. */ +int +aarch64_ext_addr_offset (const aarch64_operand *self ATTRIBUTE_UNUSED, + aarch64_opnd_info *info, + aarch64_insn code, const aarch64_inst *inst) +{ + info->qualifier = get_expected_qualifier (inst, info->idx); + + /* Rn */ + info->addr.base_regno = extract_field (self->fields[0], code, 0); + + /* simm9 */ + aarch64_insn imm = extract_fields (code, 0, 1, self->fields[1]); + info->addr.offset.imm = sign_extend (imm, 8); + if (extract_field (self->fields[2], code, 0) == 1) { + info->addr.writeback = 1; + info->addr.preind = 1; + } + return 1; +} + /* Decode the address operand for e.g. STR , [, {, {}}]. */ int @@ -981,6 +1058,27 @@ aarch64_ext_addr_uimm12 (const aarch64_operand *self, aarch64_opnd_info *info, return 1; } +/* Decode the address operand for e.g. LDRAA , [{, #}]. */ +int +aarch64_ext_addr_simm10 (const aarch64_operand *self, aarch64_opnd_info *info, + aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + aarch64_insn imm; + + info->qualifier = get_expected_qualifier (inst, info->idx); + /* Rn */ + info->addr.base_regno = extract_field (self->fields[0], code, 0); + /* simm10 */ + imm = extract_fields (code, 0, 2, self->fields[1], self->fields[2]); + info->addr.offset.imm = sign_extend (imm, 9) << 3; + if (extract_field (self->fields[3], code, 0) == 1) { + info->addr.writeback = 1; + info->addr.preind = 1; + } + return 1; +} + /* Decode the address operand for e.g. LD1 {., ., .}, [], >. */ int @@ -1301,6 +1399,18 @@ aarch64_ext_sve_addr_reg_imm (const aarch64_operand *self, return 1; } +/* Decode an SVE address [X, # << ], where + is a 4-bit signed number and where is SELF's operand-dependent + value. fields[0] specifies the base register field. */ +int +aarch64_ext_sve_addr_ri_s4 (const aarch64_operand *self, + aarch64_opnd_info *info, aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + int offset = sign_extend (extract_field (FLD_SVE_imm4, code, 0), 3); + return aarch64_ext_sve_addr_reg_imm (self, info, code, offset); +} + /* Decode an SVE address [X, # << ], where is a 6-bit unsigned number and where is SELF's operand-dependent value. fields[0] specifies the base register field. */ @@ -1321,14 +1431,14 @@ aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self, aarch64_opnd_info *info, aarch64_insn code, const aarch64_inst *inst ATTRIBUTE_UNUSED) { - int index; + int index_regno; - index = extract_field (self->fields[1], code, 0); - if (index == 31 && (self->flags & OPD_F_NO_ZR) != 0) + index_regno = extract_field (self->fields[1], code, 0); + if (index_regno == 31 && (self->flags & OPD_F_NO_ZR) != 0) return 0; info->addr.base_regno = extract_field (self->fields[0], code, 0); - info->addr.offset.regno = index; + info->addr.offset.regno = index_regno; info->addr.offset.is_reg = TRUE; info->addr.writeback = FALSE; info->addr.preind = TRUE; @@ -1528,7 +1638,7 @@ aarch64_ext_sve_index (const aarch64_operand *self, info->reglane.regno = extract_field (self->fields[0], code, 0); val = extract_fields (code, 0, 2, FLD_SVE_tszh, FLD_imm5); - if ((val & 15) == 0) + if ((val & 31) == 0) return 0; while ((val & 1) == 0) val /= 2; @@ -1547,6 +1657,21 @@ aarch64_ext_sve_limm_mov (const aarch64_operand *self, && aarch64_sve_dupm_mov_immediate_p (info->imm.value, esize)); } +/* Decode Zn[MM], where Zn occupies the least-significant part of the field + and where MM occupies the most-significant part. The operand-dependent + value specifies the number of bits in Zn. */ +int +aarch64_ext_sve_quad_index (const aarch64_operand *self, + aarch64_opnd_info *info, aarch64_insn code, + const aarch64_inst *inst ATTRIBUTE_UNUSED) +{ + unsigned int reg_bits = get_operand_specific_data (self); + unsigned int val = extract_all_fields (self, code); + info->reglane.regno = val & ((1 << reg_bits) - 1); + info->reglane.index = val >> reg_bits; + return 1; +} + /* Decode {Zn. - Zm.}. The fields array specifies which field to use for Zn. The opcode-dependent value specifies the number of registers in the list. */ @@ -1844,7 +1969,7 @@ do_misc_decoding (aarch64_inst *inst) case OP_MOV_Z_V: /* Index must be zero. */ value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5); - return value == 1 || value == 2 || value == 4 || value == 8; + return value > 0 && value <= 16 && value == (value & -value); case OP_MOV_Z_Z: return (extract_field (FLD_SVE_Zn, inst->value, 0) @@ -1853,7 +1978,7 @@ do_misc_decoding (aarch64_inst *inst) case OP_MOV_Z_Zi: /* Index must be nonzero. */ value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5); - return value != 1 && value != 2 && value != 4 && value != 8; + return value > 0 && value != (value & -value); case OP_MOVM_P_P_P: return (extract_field (FLD_SVE_Pd, inst->value, 0) @@ -2259,7 +2384,7 @@ convert_movewide_to_mov (aarch64_inst *inst) int is32 = inst->operands[0].qualifier == AARCH64_OPND_QLF_W; value = ~value; /* A MOVN has an immediate that could be encoded by MOVZ. */ - if (aarch64_wide_constant_p (value, is32, NULL) == TRUE) + if (aarch64_wide_constant_p (value, is32, NULL)) return 0; } inst->operands[1].imm.value = value; @@ -2292,8 +2417,8 @@ convert_movebitmask_to_mov (aarch64_inst *inst) /* ORR has an immediate that could be generated by a MOVZ or MOVN instruction. */ if (inst->operands[0].reg.regno != 0x1f - && (aarch64_wide_constant_p (value, is32, NULL) == TRUE - || aarch64_wide_constant_p (~value, is32, NULL) == TRUE)) + && (aarch64_wide_constant_p (value, is32, NULL) + || aarch64_wide_constant_p (~value, is32, NULL))) return 0; inst->operands[2].type = AARCH64_OPND_NIL; @@ -2414,7 +2539,7 @@ determine_disassembling_preference (struct aarch64_inst *inst) opcode = inst->opcode; /* This opcode does not have an alias, so use itself. */ - if (opcode_has_alias (opcode) == FALSE) + if (!opcode_has_alias (opcode)) return; alias = aarch64_find_alias_opcode (opcode); @@ -2510,8 +2635,8 @@ aarch64_decode_variant_using_iclass (aarch64_inst *inst) break; case sve_index: - i = extract_field (FLD_SVE_tsz, inst->value, 0); - if (i == 0) + i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5); + if ((i & 31) == 0) return FALSE; while ((i & 1) == 0) { @@ -2972,6 +3097,10 @@ get_sym_code_type (struct disassemble_info *info, int n, unsigned int type; const char *name; + /* If the symbol is in a different section, ignore it. */ + if (info->section != NULL && info->section != info->symtab[n]->section) + return FALSE; + es = *(elf_symbol_type **)(info->symtab + n); type = ELF_ST_TYPE (es->internal_elf_sym.st_info); @@ -3046,9 +3175,7 @@ print_insn_aarch64 (bfd_vma pc, addr = bfd_asymbol_value (info->symtab[n]); if (addr > pc) break; - if ((info->section == NULL - || info->section == info->symtab[n]->section) - && get_sym_code_type (info, n, &type)) + if (get_sym_code_type (info, n, &type)) { last_sym = n; found = TRUE;