/* aarch64-dis.c -- AArch64 disassembler.
- Copyright 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
+ Copyright (C) 2009-2014 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of the GNU opcodes library.
N.B. the fields are required to be in such an order than the most signficant
field for VALUE comes the first, e.g. the <index> in
SQDMLAL <Va><d>, <Vb><n>, <Vm>.<Ts>[<index>]
- is encoded in H:L:M in some cases, the the fields H:L:M should be passed in
+ is encoded in H:L:M in some cases, the fields H:L:M should be passed in
the order of H, L, M. */
static inline aarch64_insn
return 1;
}
+int
+aarch64_ext_regno_pair (const aarch64_operand *self ATTRIBUTE_UNUSED, aarch64_opnd_info *info,
+ const aarch64_insn code ATTRIBUTE_UNUSED,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ assert (info->idx == 1
+ || info->idx ==3);
+ info->reg.regno = inst->operands[info->idx - 1].reg.regno + 1;
+ return 1;
+}
+
/* e.g. IC <ic_op>{, <Xt>}. */
int
aarch64_ext_regrt_sysins (const aarch64_operand *self, aarch64_opnd_info *info,
info->reglist.index = QSsize;
break;
case 0x1:
+ if (QSsize & 0x1)
+ /* UND. */
+ return 0;
info->qualifier = AARCH64_OPND_QLF_S_H;
/* Index encoded in "Q:S:size<1>". */
info->reglist.index = QSsize >> 1;
break;
case 0x2:
+ if ((QSsize >> 1) & 0x1)
+ /* UND. */
+ return 0;
if ((QSsize & 0x1) == 0)
{
info->qualifier = AARCH64_OPND_QLF_S_S;
}
else
{
- info->qualifier = AARCH64_OPND_QLF_S_D;
- /* Index encoded in "Q". */
- info->reglist.index = QSsize >> 3;
if (extract_field (FLD_S, code, 0))
/* UND */
return 0;
+ info->qualifier = AARCH64_OPND_QLF_S_D;
+ /* Index encoded in "Q". */
+ info->reglist.index = QSsize >> 3;
}
break;
default:
&& extract_field (FLD_N, inst->value, 0) != value)
return 0;
}
+ /* 'sf' field. */
+ if (inst->opcode->flags & F_LSE_SZ)
+ {
+ idx = select_operand_for_sf_field_coding (inst->opcode);
+ value = extract_field (FLD_lse_sz, inst->value, 0);
+ inst->operands[idx].qualifier = get_greg_qualifier_from_value (value);
+ }
/* size:Q fields. */
if (inst->opcode->flags & F_SIZEQ)
return decode_sizeq (inst);
/* CINC <Wd>, <Wn>, <cond>
is equivalent to:
- CSINC <Wd>, <Wn>, <Wn>, invert(<cond>). */
+ CSINC <Wd>, <Wn>, <Wn>, invert(<cond>)
+ where <cond> is not AL or NV. */
static int
convert_from_csel (aarch64_inst *inst)
{
- if (inst->operands[1].reg.regno == inst->operands[2].reg.regno)
+ if (inst->operands[1].reg.regno == inst->operands[2].reg.regno
+ && (inst->operands[3].cond->value & 0xe) != 0xe)
{
copy_operand_info (inst, 2, 3);
inst->operands[2].cond = get_inverted_cond (inst->operands[3].cond);
/* CSET <Wd>, <cond>
is equivalent to:
- CSINC <Wd>, WZR, WZR, invert(<cond>). */
+ CSINC <Wd>, WZR, WZR, invert(<cond>)
+ where <cond> is not AL or NV. */
static int
convert_csinc_to_cset (aarch64_inst *inst)
{
if (inst->operands[1].reg.regno == 0x1f
- && inst->operands[2].reg.regno == 0x1f)
+ && inst->operands[2].reg.regno == 0x1f
+ && (inst->operands[3].cond->value & 0xe) != 0xe)
{
copy_operand_info (inst, 1, 3);
inst->operands[1].cond = get_inverted_cond (inst->operands[3].cond);