X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=opcodes%2Faarch64-asm.c;h=afb0e5b4d2ad0e62307e97858062f8599169248e;hb=fd1dc4a0c1b87c1efa7e0398fd47fd1e87fa0fb4;hp=06d428bf193d0720770f6324bfc92c54416321ee;hpb=f9830ec1655e7cc2aa88c9c34a20503978d9dc88;p=external%2Fbinutils.git diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c index 06d428b..afb0e5b 100644 --- a/opcodes/aarch64-asm.c +++ b/opcodes/aarch64-asm.c @@ -1,5 +1,5 @@ /* aarch64-asm.c -- AArch64 assembler support. - Copyright (C) 2012-2018 Free Software Foundation, Inc. + Copyright (C) 2012-2019 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of the GNU opcodes library. @@ -381,6 +381,8 @@ aarch64_ins_imm (const aarch64_operand *self, const aarch64_opnd_info *info, imm = info->imm.value; if (operand_need_shift_by_two (self)) imm >>= 2; + if (operand_need_shift_by_four (self)) + imm >>= 4; insert_all_fields (self, code, imm); return TRUE; } @@ -688,7 +690,8 @@ aarch64_ins_addr_simm (const aarch64_operand *self, insert_field (FLD_Rn, code, info->addr.base_regno, 0); /* simm (imm9 or imm7) */ imm = info->addr.offset.imm; - if (self->fields[0] == FLD_imm7) + if (self->fields[0] == FLD_imm7 + || info->qualifier == AARCH64_OPND_QLF_imm_tag) /* scaled immediate in ld/st pair instructions.. */ imm >>= get_logsz (aarch64_get_qualifier_esize (info->qualifier)); insert_field (self->fields[0], code, imm, 0); @@ -1238,8 +1241,9 @@ aarch64_ins_sve_shrimm (const aarch64_operand *self, const aarch64_opnd_info *prev_operand; unsigned int esize; - assert (info->idx > 0); - prev_operand = &inst->operands[info->idx - 1]; + unsigned int opnd_backshift = get_operand_specific_data (self); + assert (info->idx >= (int)opnd_backshift); + prev_operand = &inst->operands[info->idx - opnd_backshift]; esize = aarch64_get_qualifier_esize (prev_operand->qualifier); insert_all_fields (self, code, 16 * esize - info->imm.value); return TRUE; @@ -1610,6 +1614,7 @@ do_special_encoding (struct aarch64_inst *inst) static void aarch64_encode_variant_using_iclass (struct aarch64_inst *inst) { + int variant = 0; switch (inst->opcode->iclass) { case sve_cpy: @@ -1620,6 +1625,8 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst) case sve_index: case sve_shift_pred: case sve_shift_unpred: + case sve_shift_tsz_hsd: + case sve_shift_tsz_bhsd: /* For indices and shift amounts, the variant is encoded as part of the immediate. */ break; @@ -1652,10 +1659,33 @@ aarch64_encode_variant_using_iclass (struct aarch64_inst *inst) insert_field (FLD_size, &inst->value, aarch64_get_variant (inst) + 1, 0); break; + case sve_size_bh: case sve_size_sd: insert_field (FLD_SVE_sz, &inst->value, aarch64_get_variant (inst), 0); break; + case sve_size_sd2: + insert_field (FLD_SVE_sz2, &inst->value, aarch64_get_variant (inst), 0); + break; + + case sve_size_hsd2: + insert_field (FLD_SVE_size, &inst->value, + aarch64_get_variant (inst) + 1, 0); + break; + + case sve_size_tsz_bhs: + insert_fields (&inst->value, + (1 << aarch64_get_variant (inst)), + 0, 2, FLD_SVE_tszl_19, FLD_SVE_sz); + break; + + case sve_size_013: + variant = aarch64_get_variant (inst); + if (variant == 2) + variant = 3; + insert_field (FLD_size, &inst->value, variant, 0); + break; + default: break; } @@ -1948,7 +1978,8 @@ bfd_boolean aarch64_opcode_encode (const aarch64_opcode *opcode, const aarch64_inst *inst_ori, aarch64_insn *code, aarch64_opnd_qualifier_t *qlf_seq, - aarch64_operand_error *mismatch_detail) + aarch64_operand_error *mismatch_detail, + aarch64_instr_sequence* insn_sequence) { int i; const aarch64_opcode *aliased; @@ -2035,6 +2066,38 @@ aarch64_opcode_encode (const aarch64_opcode *opcode, variant. */ aarch64_encode_variant_using_iclass (inst); + /* Run a verifier if the instruction has one set. */ + if (opcode->verifier) + { + enum err_type result = opcode->verifier (inst, *code, 0, TRUE, + mismatch_detail, insn_sequence); + switch (result) + { + case ERR_UND: + case ERR_UNP: + case ERR_NYI: + return FALSE; + default: + break; + } + } + + /* Always run constrain verifiers, this is needed because constrains need to + maintain a global state. Regardless if the instruction has the flag set + or not. */ + enum err_type result = verify_constraints (inst, *code, 0, TRUE, + mismatch_detail, insn_sequence); + switch (result) + { + case ERR_UND: + case ERR_UNP: + case ERR_NYI: + return FALSE; + default: + break; + } + + encoding_exit: DEBUG_TRACE ("exit with %s", opcode->name);