diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:58:22 +0100 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2016-09-21 16:58:22 +0100 |
commit | 116b60193779ac65a29fb3688b753527980cb3e7 (patch) | |
tree | 40eaa4854176b9fcdf985ae996869ed62f2225b3 /opcodes/aarch64-asm.c | |
parent | 047cd301d40288d13e44f3322541ac28ebe06078 (diff) | |
download | gdb-116b60193779ac65a29fb3688b753527980cb3e7.zip gdb-116b60193779ac65a29fb3688b753527980cb3e7.tar.gz 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-asm.c')
-rw-r--r-- | opcodes/aarch64-asm.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/opcodes/aarch64-asm.c b/opcodes/aarch64-asm.c index fd356f4..78fd272 100644 --- a/opcodes/aarch64-asm.c +++ b/opcodes/aarch64-asm.c @@ -1140,6 +1140,27 @@ encode_fcvt (aarch64_inst *inst) return; } +/* Return the index in qualifiers_list that INST is using. Should only + be called once the qualifiers are known to be valid. */ + +static int +aarch64_get_variant (struct aarch64_inst *inst) +{ + int i, nops, variant; + + nops = aarch64_num_of_operands (inst->opcode); + for (variant = 0; variant < AARCH64_MAX_QLF_SEQ_NUM; ++variant) + { + for (i = 0; i < nops; ++i) + if (inst->opcode->qualifiers_list[variant][i] + != inst->operands[i].qualifier) + break; + if (i == nops) + return variant; + } + abort (); +} + /* Do miscellaneous encodings that are not common enough to be driven by flags. */ @@ -1318,6 +1339,65 @@ do_special_encoding (struct aarch64_inst *inst) DEBUG_TRACE ("exit with coding 0x%x", (uint32_t) inst->value); } +/* 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, encode the chosen qualifier + variant. */ + +static void +aarch64_encode_variant_using_iclass (struct aarch64_inst *inst) +{ + switch (inst->opcode->iclass) + { + case sve_cpy: + insert_fields (&inst->value, aarch64_get_variant (inst), + 0, 2, FLD_SVE_M_14, FLD_size); + break; + + case sve_index: + case sve_shift_pred: + case sve_shift_unpred: + /* For indices and shift amounts, the variant is encoded as + part of the immediate. */ + break; + + case sve_limm: + /* For sve_limm, the .B, .H, and .S forms are just a convenience + and depend on the immediate. They don't have a separate + encoding. */ + break; + + case sve_misc: + /* sve_misc instructions have only a single variant. */ + break; + + case sve_movprfx: + insert_fields (&inst->value, aarch64_get_variant (inst), + 0, 2, FLD_SVE_M_16, FLD_size); + break; + + case sve_pred_zm: + insert_field (FLD_SVE_M_4, &inst->value, aarch64_get_variant (inst), 0); + break; + + case sve_size_bhs: + case sve_size_bhsd: + insert_field (FLD_size, &inst->value, aarch64_get_variant (inst), 0); + break; + + case sve_size_hsd: + insert_field (FLD_size, &inst->value, aarch64_get_variant (inst) + 1, 0); + break; + + case sve_size_sd: + insert_field (FLD_SVE_sz, &inst->value, aarch64_get_variant (inst), 0); + break; + + default: + break; + } +} + /* Converters converting an alias opcode instruction to its real form. */ /* ROR <Wd>, <Ws>, #<shift> @@ -1686,6 +1766,10 @@ aarch64_opcode_encode (const aarch64_opcode *opcode, if (opcode_has_special_coder (opcode)) do_special_encoding (inst); + /* Possibly use the instruction class to encode the chosen qualifier + variant. */ + aarch64_encode_variant_using_iclass (inst); + encoding_exit: DEBUG_TRACE ("exit with %s", opcode->name); |