aboutsummaryrefslogtreecommitdiff
path: root/opcodes/aarch64-dis.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:58:22 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:58:22 +0100
commit116b60193779ac65a29fb3688b753527980cb3e7 (patch)
tree40eaa4854176b9fcdf985ae996869ed62f2225b3 /opcodes/aarch64-dis.c
parent047cd301d40288d13e44f3322541ac28ebe06078 (diff)
downloadfsf-binutils-gdb-116b60193779ac65a29fb3688b753527980cb3e7.zip
fsf-binutils-gdb-116b60193779ac65a29fb3688b753527980cb3e7.tar.gz
fsf-binutils-gdb-116b60193779ac65a29fb3688b753527980cb3e7.tar.bz2
[AArch64][SVE 30/32] Add SVE instruction classes
The main purpose of the SVE aarch64_insn_classes is to describe how an index into an aarch64_opnd_qualifier_seq_t is represented in the instruction encoding. Other instructions usually use flags for this information, but (a) we're running out of those and (b) the iclass would otherwise be unused for SVE. include/ * opcode/aarch64.h (sve_cpy, sve_index, sve_limm, sve_misc) (sve_movprfx, sve_pred_zm, sve_shift_pred, sve_shift_unpred) (sve_size_bhs, sve_size_bhsd, sve_size_hsd, sve_size_sd): New aarch64_insn_classes. opcodes/ * aarch64-opc.h (FLD_SVE_M_4, FLD_SVE_M_14, FLD_SVE_M_16) (FLD_SVE_sz, FLD_SVE_tsz, FLD_SVE_tszl_8, FLD_SVE_tszl_19): New aarch64_field_kinds. * aarch64-opc.c (fields): Add corresponding entries. * aarch64-asm.c (aarch64_get_variant): New function. (aarch64_encode_variant_using_iclass): Likewise. (aarch64_opcode_encode): Call it. * aarch64-dis.c (aarch64_decode_variant_using_iclass): New function. (aarch64_opcode_decode): Call it.
Diffstat (limited to 'opcodes/aarch64-dis.c')
-rw-r--r--opcodes/aarch64-dis.c107
1 files changed, 107 insertions, 0 deletions
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 385286c..f84f216 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -2444,6 +2444,105 @@ determine_disassembling_preference (struct aarch64_inst *inst)
}
}
+/* Some instructions (including all SVE ones) use the instruction class
+ to describe how a qualifiers_list index is represented in the instruction
+ encoding. If INST is such an instruction, decode the appropriate fields
+ and fill in the operand qualifiers accordingly. Return true if no
+ problems are found. */
+
+static bfd_boolean
+aarch64_decode_variant_using_iclass (aarch64_inst *inst)
+{
+ int i, variant;
+
+ variant = 0;
+ switch (inst->opcode->iclass)
+ {
+ case sve_cpy:
+ variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_14);
+ break;
+
+ case sve_index:
+ i = extract_field (FLD_SVE_tsz, inst->value, 0);
+ if (i == 0)
+ return FALSE;
+ while ((i & 1) == 0)
+ {
+ i >>= 1;
+ variant += 1;
+ }
+ break;
+
+ case sve_limm:
+ /* Pick the smallest applicable element size. */
+ if ((inst->value & 0x20600) == 0x600)
+ variant = 0;
+ else if ((inst->value & 0x20400) == 0x400)
+ variant = 1;
+ else if ((inst->value & 0x20000) == 0)
+ variant = 2;
+ else
+ variant = 3;
+ break;
+
+ case sve_misc:
+ /* sve_misc instructions have only a single variant. */
+ break;
+
+ case sve_movprfx:
+ variant = extract_fields (inst->value, 0, 2, FLD_size, FLD_SVE_M_16);
+ break;
+
+ case sve_pred_zm:
+ variant = extract_field (FLD_SVE_M_4, inst->value, 0);
+ break;
+
+ case sve_shift_pred:
+ i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_8);
+ sve_shift:
+ if (i == 0)
+ return FALSE;
+ while (i != 1)
+ {
+ i >>= 1;
+ variant += 1;
+ }
+ break;
+
+ case sve_shift_unpred:
+ i = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_SVE_tszl_19);
+ goto sve_shift;
+
+ case sve_size_bhs:
+ variant = extract_field (FLD_size, inst->value, 0);
+ if (variant >= 3)
+ return FALSE;
+ break;
+
+ case sve_size_bhsd:
+ variant = extract_field (FLD_size, inst->value, 0);
+ break;
+
+ case sve_size_hsd:
+ i = extract_field (FLD_size, inst->value, 0);
+ if (i < 1)
+ return FALSE;
+ variant = i - 1;
+ break;
+
+ case sve_size_sd:
+ variant = extract_field (FLD_SVE_sz, inst->value, 0);
+ break;
+
+ default:
+ /* No mapping between instruction class and qualifiers. */
+ return TRUE;
+ }
+
+ for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
+ inst->operands[i].qualifier = inst->opcode->qualifiers_list[variant][i];
+ return TRUE;
+}
/* Decode the CODE according to OPCODE; fill INST. Return 0 if the decoding
fails, which meanes that CODE is not an instruction of OPCODE; otherwise
return 1.
@@ -2491,6 +2590,14 @@ aarch64_opcode_decode (const aarch64_opcode *opcode, const aarch64_insn code,
goto decode_fail;
}
+ /* Possibly use the instruction class to determine the correct
+ qualifier. */
+ if (!aarch64_decode_variant_using_iclass (inst))
+ {
+ DEBUG_TRACE ("iclass-based decoder FAIL");
+ goto decode_fail;
+ }
+
/* Call operand decoders. */
for (i = 0; i < AARCH64_MAX_OPND_NUM; ++i)
{