diff options
Diffstat (limited to 'opcodes/aarch64-opc.h')
-rw-r--r-- | opcodes/aarch64-opc.h | 95 |
1 files changed, 75 insertions, 20 deletions
diff --git a/opcodes/aarch64-opc.h b/opcodes/aarch64-opc.h index 9ab9bdf..5d544d5 100644 --- a/opcodes/aarch64-opc.h +++ b/opcodes/aarch64-opc.h @@ -30,6 +30,10 @@ enum aarch64_field_kind { FLD_NIL, + FLD_CONST_0, + FLD_CONST_00, + FLD_CONST_01, + FLD_CONST_1, FLD_CRm, FLD_CRm_dsb_nxs, FLD_CRn, @@ -66,10 +70,12 @@ enum aarch64_field_kind FLD_SME_Zdn2, FLD_SME_Zdn4, FLD_SME_Zm, + FLD_SME_Zm17_3, FLD_SME_Zm2, FLD_SME_Zm4, FLD_SME_Zn2, FLD_SME_Zn4, + FLD_SME_Zn6_3, FLD_SME_ZtT, FLD_SME_Zt3, FLD_SME_Zt2, @@ -133,6 +139,8 @@ enum aarch64_field_kind FLD_SVE_size, FLD_SVE_sz, FLD_SVE_sz2, + FLD_SVE_sz3, + FLD_SVE_sz4, FLD_SVE_tsz, FLD_SVE_tszh, FLD_SVE_tszl_8, @@ -160,6 +168,7 @@ enum aarch64_field_kind FLD_imm2_0, FLD_imm2_1, FLD_imm2_2, + FLD_imm2_4, FLD_imm2_8, FLD_imm2_10, FLD_imm2_12, @@ -185,6 +194,7 @@ enum aarch64_field_kind FLD_imm7, FLD_imm8, FLD_imm9, + FLD_imm9_5, FLD_imm12, FLD_imm14, FLD_imm16_0, @@ -239,16 +249,42 @@ enum aarch64_field_kind FLD_ZA5_4, }; -/* Field description. */ +/* Field description. + + If is_const is false, this identifies a bitfield in an instruction encoding + that has size WIDTH and has its least significant bit at position NUM. + + If is_const is true, this represents the constant bit string of size WIDTH + bits stored in the least significant bits of NUM. In this case, the + leading 8-WIDTH bits of VALUE must be zero. + + A sequence of fields can be used to describe how instruction operands are + represented in the 32-bit instruction encoding. + + For example, consider an instruction operand Zd that is an even numbered + register in z16-z30, with the middle three bits of the register number + stored in bits [19:17] of the encoding. The register number can then be + constructed by concatenating: + - a constant bit '1' (represented here as {1, 1, true}), + - bits [19:17] of the encoding (represented here as {3, 17, false}), and + - a constant bit '0' (represented here as {1, 0, true}). + This sequence of fields fully describes both the constraints on which + register numbers are valid, and how valid register numbers are represented + in the instruction encoding. */ struct aarch64_field { - int lsb; - int width; + unsigned int width:8; + unsigned int num:7; + bool is_const:1; }; typedef struct aarch64_field aarch64_field; -extern const aarch64_field fields[]; +#define AARCH64_FIELD(lsb, width) {width, lsb, false} +#define AARCH64_FIELD_CONST(val, width) {width, val, true} +#define AARCH64_FIELD_NIL {0, 0, false} + +extern const aarch64_field aarch64_fields[]; /* Operand description. */ @@ -262,9 +298,9 @@ struct aarch64_operand unsigned int flags; - /* The associated instruction bit-fields; no operand has more than 4 + /* The associated instruction bit-fields; no operand has more than 5 bit-fields */ - enum aarch64_field_kind fields[5]; + enum aarch64_field_kind fields[6]; /* Brief description */ const char *desc; @@ -304,8 +340,7 @@ verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, #undef F_DEPRECATED #define F_DEPRECATED (1 << 0) /* Deprecated system register. */ -#undef F_ARCHEXT -#define F_ARCHEXT (1 << 1) /* Architecture dependent system register. */ +/* (1 << 1) Unused. */ #undef F_HASXT #define F_HASXT (1 << 2) /* System instruction register <Xt> @@ -326,7 +361,7 @@ verify_constraints (const struct aarch64_inst *, const aarch64_insn, bfd_vma, #define F_REG_ALIAS (1 << 6) /* Register name aliases another. */ #undef F_REG_128 -#define F_REG_128 (1 << 7) /* System regsister implementable as 128-bit wide. */ +#define F_REG_128 (1 << 7) /* System register implementable as 128-bit wide. */ /* PSTATE field name for the MSR instruction this is encoded in "op1:op2:CRm". @@ -424,7 +459,7 @@ static inline unsigned get_operand_field_width (const aarch64_operand *operand, unsigned n) { assert (operand->fields[n] != FLD_NIL); - return fields[operand->fields[n]].width; + return aarch64_fields[operand->fields[n]].width; } /* Return the total width of the operand *OPERAND. */ @@ -434,7 +469,7 @@ get_operand_fields_width (const aarch64_operand *operand) int i = 0; unsigned width = 0; while (operand->fields[i] != FLD_NIL) - width += fields[operand->fields[i++]].width; + width += aarch64_fields[operand->fields[i++]].width; assert (width > 0 && width < 32); return width; } @@ -479,10 +514,10 @@ gen_mask (int width) static inline int gen_sub_field (enum aarch64_field_kind kind, int lsb_rel, int width, aarch64_field *ret) { - const aarch64_field *field = &fields[kind]; + const aarch64_field *field = &aarch64_fields[kind]; if (lsb_rel < 0 || width <= 0 || lsb_rel + width > field->width) return 0; - ret->lsb = field->lsb + lsb_rel; + ret->num = field->num + lsb_rel; ret->width = width; return 1; } @@ -494,10 +529,16 @@ static inline void insert_field_2 (const aarch64_field *field, aarch64_insn *code, aarch64_insn value, aarch64_insn mask) { - assert (field->width < 32 && field->width >= 1 && field->lsb >= 0 - && field->lsb + field->width <= 32); + assert (field->width < 32 && field->width >= 1 + && (field->is_const ? (field->num < 1 << field->width) + : (field->num + field->width <= 32))); value &= gen_mask (field->width); - value <<= field->lsb; + if (field->is_const) + { + assert (value == field->num); + return; + } + value <<= field->num; /* In some opcodes, field can be part of the base opcode, e.g. the size field in FADD. The following helps avoid corrupt the base opcode. */ value &= ~mask; @@ -512,9 +553,13 @@ extract_field_2 (const aarch64_field *field, aarch64_insn code, aarch64_insn mask) { aarch64_insn value; + /* Check for constant field. */ + if (field->is_const) + return field->num; + /* Clear any bit that is a part of the base opcode. */ code &= ~mask; - value = (code >> field->lsb) & gen_mask (field->width); + value = (code >> field->num) & gen_mask (field->width); return value; } @@ -525,7 +570,7 @@ static inline void insert_field (enum aarch64_field_kind kind, aarch64_insn *code, aarch64_insn value, aarch64_insn mask) { - insert_field_2 (&fields[kind], code, value, mask); + insert_field_2 (&aarch64_fields[kind], code, value, mask); } /* Extract field KIND of CODE and return the value. MASK can be zero or the @@ -535,7 +580,7 @@ static inline aarch64_insn extract_field (enum aarch64_field_kind kind, aarch64_insn code, aarch64_insn mask) { - return extract_field_2 (&fields[kind], code, mask); + return extract_field_2 (&aarch64_fields[kind], code, mask); } extern aarch64_insn @@ -551,6 +596,11 @@ static inline int select_operand_for_sf_field_coding (const aarch64_opcode *opcode) { int idx = -1; + if (opcode->iclass == fprcvtfloat2int) + return 0; + else if (opcode->iclass == fprcvtint2float) + return 1; + if (aarch64_get_operand_class (opcode->operands[0]) == AARCH64_OPND_CLASS_INT_REG) /* normal case. */ @@ -572,6 +622,11 @@ static inline int select_operand_for_fptype_field_coding (const aarch64_opcode *opcode) { int idx; + if (opcode->iclass == fprcvtfloat2int) + return 1; + else if (opcode->iclass == fprcvtint2float) + return 0; + if (aarch64_get_operand_class (opcode->operands[1]) == AARCH64_OPND_CLASS_FP_REG) /* normal case. */ @@ -602,7 +657,7 @@ select_operand_for_scalar_size_field_coding (const aarch64_opcode *opcode) src_size = aarch64_get_qualifier_esize (opcode->qualifiers_list[0][1]); if (src_size == dst_size && src_size == 0) { assert (0); abort (); } - /* When the result is not a sisd register or it is a long operantion. */ + /* When the result is not a sisd register or it is a long operation. */ if (dst_size == 0 || dst_size == src_size << 1) return 1; else |