aboutsummaryrefslogtreecommitdiff
path: root/opcodes/aarch64-dis.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:55:49 +0100
committerRichard Sandiford <richard.sandiford@arm.com>2016-09-21 16:55:49 +0100
commit4df068de5214ff55b01ae320ec580f2928eb74e5 (patch)
tree8ca6efd2456f0f920e8cd9ac5bb5dcb9614a84e0 /opcodes/aarch64-dis.c
parent2442d8466e221ba6cf4ec4bd2a819fdcb1e5ea7e (diff)
downloadgdb-4df068de5214ff55b01ae320ec580f2928eb74e5.zip
gdb-4df068de5214ff55b01ae320ec580f2928eb74e5.tar.gz
gdb-4df068de5214ff55b01ae320ec580f2928eb74e5.tar.bz2
[AArch64][SVE 25/32] Add support for SVE addressing modes
This patch adds most of the new SVE addressing modes and associated operands. A follow-on patch adds MUL VL, since handling it separately makes the changes easier to read. The patch also introduces a new "operand-dependent data" field to the operand flags, based closely on the existing one for opcode flags. For SVE this new field needs only 2 bits, but it could be widened in future if necessary. include/ * opcode/aarch64.h (AARCH64_OPND_SVE_ADDR_RI_U6): New aarch64_opnd. (AARCH64_OPND_SVE_ADDR_RI_U6x2, AARCH64_OPND_SVE_ADDR_RI_U6x4) (AARCH64_OPND_SVE_ADDR_RI_U6x8, AARCH64_OPND_SVE_ADDR_RR) (AARCH64_OPND_SVE_ADDR_RR_LSL1, AARCH64_OPND_SVE_ADDR_RR_LSL2) (AARCH64_OPND_SVE_ADDR_RR_LSL3, AARCH64_OPND_SVE_ADDR_RX) (AARCH64_OPND_SVE_ADDR_RX_LSL1, AARCH64_OPND_SVE_ADDR_RX_LSL2) (AARCH64_OPND_SVE_ADDR_RX_LSL3, AARCH64_OPND_SVE_ADDR_RZ) (AARCH64_OPND_SVE_ADDR_RZ_LSL1, AARCH64_OPND_SVE_ADDR_RZ_LSL2) (AARCH64_OPND_SVE_ADDR_RZ_LSL3, AARCH64_OPND_SVE_ADDR_RZ_XTW_14) (AARCH64_OPND_SVE_ADDR_RZ_XTW_22, AARCH64_OPND_SVE_ADDR_RZ_XTW1_14) (AARCH64_OPND_SVE_ADDR_RZ_XTW1_22, AARCH64_OPND_SVE_ADDR_RZ_XTW2_14) (AARCH64_OPND_SVE_ADDR_RZ_XTW2_22, AARCH64_OPND_SVE_ADDR_RZ_XTW3_14) (AARCH64_OPND_SVE_ADDR_RZ_XTW3_22, AARCH64_OPND_SVE_ADDR_ZI_U5) (AARCH64_OPND_SVE_ADDR_ZI_U5x2, AARCH64_OPND_SVE_ADDR_ZI_U5x4) (AARCH64_OPND_SVE_ADDR_ZI_U5x8, AARCH64_OPND_SVE_ADDR_ZZ_LSL) (AARCH64_OPND_SVE_ADDR_ZZ_SXTW, AARCH64_OPND_SVE_ADDR_ZZ_UXTW): Likewise. opcodes/ * aarch64-tbl.h (AARCH64_OPERANDS): Add entries for the new SVE address operands. * aarch64-opc.h (FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14) (FLD_SVE_xs_22): New aarch64_field_kinds. (OPD_F_OD_MASK, OPD_F_OD_LSB, OPD_F_NO_ZR): New flags. (get_operand_specific_data): New function. * aarch64-opc.c (fields): Add entries for FLD_SVE_imm6, FLD_SVE_msz, FLD_SVE_xs_14 and FLD_SVE_xs_22. (operand_general_constraint_met_p): Handle the new SVE address operands. (sve_reg): New array. (get_addr_sve_reg_name): New function. (aarch64_print_operand): Handle the new SVE address operands. * aarch64-opc-2.c: Regenerate. * aarch64-asm.h (ins_sve_addr_ri_u6, ins_sve_addr_rr_lsl) (ins_sve_addr_rz_xtw, ins_sve_addr_zi_u5, ins_sve_addr_zz_lsl) (ins_sve_addr_zz_sxtw, ins_sve_addr_zz_uxtw): New inserters. * aarch64-asm.c (aarch64_ins_sve_addr_ri_u6): New function. (aarch64_ins_sve_addr_rr_lsl): Likewise. (aarch64_ins_sve_addr_rz_xtw): Likewise. (aarch64_ins_sve_addr_zi_u5): Likewise. (aarch64_ins_sve_addr_zz): Likewise. (aarch64_ins_sve_addr_zz_lsl): Likewise. (aarch64_ins_sve_addr_zz_sxtw): Likewise. (aarch64_ins_sve_addr_zz_uxtw): Likewise. * aarch64-asm-2.c: Regenerate. * aarch64-dis.h (ext_sve_addr_ri_u6, ext_sve_addr_rr_lsl) (ext_sve_addr_rz_xtw, ext_sve_addr_zi_u5, ext_sve_addr_zz_lsl) (ext_sve_addr_zz_sxtw, ext_sve_addr_zz_uxtw): New extractors. * aarch64-dis.c (aarch64_ext_sve_add_reg_imm): New function. (aarch64_ext_sve_addr_ri_u6): Likewise. (aarch64_ext_sve_addr_rr_lsl): Likewise. (aarch64_ext_sve_addr_rz_xtw): Likewise. (aarch64_ext_sve_addr_zi_u5): Likewise. (aarch64_ext_sve_addr_zz): Likewise. (aarch64_ext_sve_addr_zz_lsl): Likewise. (aarch64_ext_sve_addr_zz_sxtw): Likewise. (aarch64_ext_sve_addr_zz_uxtw): Likewise. * aarch64-dis-2.c: Regenerate. gas/ * config/tc-aarch64.c (REG_TYPE_SVE_BASE, REG_TYPE_SVE_OFFSET): New register types. (get_reg_expected_msg): Handle them. (aarch64_addr_reg_parse): New function, split out from aarch64_reg_parse_32_64. Handle Z registers too. (aarch64_reg_parse_32_64): Call it. (parse_address_main): Add base_qualifier, offset_qualifier, base_type and offset_type parameters. Handle SVE base and offset registers. (parse_address): Update call to parse_address_main. (parse_sve_address): New function. (parse_operands): Parse the new SVE address operands.
Diffstat (limited to 'opcodes/aarch64-dis.c')
-rw-r--r--opcodes/aarch64-dis.c146
1 files changed, 146 insertions, 0 deletions
diff --git a/opcodes/aarch64-dis.c b/opcodes/aarch64-dis.c
index 1d00c0a..ed77b4d 100644
--- a/opcodes/aarch64-dis.c
+++ b/opcodes/aarch64-dis.c
@@ -1186,6 +1186,152 @@ aarch64_ext_reg_shifted (const aarch64_operand *self ATTRIBUTE_UNUSED,
return 1;
}
+/* Decode an SVE address [<base>, #<offset> << <shift>], where <offset>
+ is given by the OFFSET parameter and where <shift> is SELF's operand-
+ dependent value. fields[0] specifies the base register field <base>. */
+static int
+aarch64_ext_sve_addr_reg_imm (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ int64_t offset)
+{
+ info->addr.base_regno = extract_field (self->fields[0], code, 0);
+ info->addr.offset.imm = offset * (1 << get_operand_specific_data (self));
+ info->addr.offset.is_reg = FALSE;
+ info->addr.writeback = FALSE;
+ info->addr.preind = TRUE;
+ info->shifter.operator_present = FALSE;
+ info->shifter.amount_present = FALSE;
+ return 1;
+}
+
+/* Decode an SVE address [X<n>, #<SVE_imm6> << <shift>], where <SVE_imm6>
+ is a 6-bit unsigned number and where <shift> is SELF's operand-dependent
+ value. fields[0] specifies the base register field. */
+int
+aarch64_ext_sve_addr_ri_u6 (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int offset = extract_field (FLD_SVE_imm6, code, 0);
+ return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
+}
+
+/* Decode an SVE address [X<n>, X<m>{, LSL #<shift>}], where <shift>
+ is SELF's operand-dependent value. fields[0] specifies the base
+ register field and fields[1] specifies the offset register field. */
+int
+aarch64_ext_sve_addr_rr_lsl (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int index;
+
+ index = extract_field (self->fields[1], code, 0);
+ if (index == 31 && (self->flags & OPD_F_NO_ZR) != 0)
+ return 0;
+
+ info->addr.base_regno = extract_field (self->fields[0], code, 0);
+ info->addr.offset.regno = index;
+ info->addr.offset.is_reg = TRUE;
+ info->addr.writeback = FALSE;
+ info->addr.preind = TRUE;
+ info->shifter.kind = AARCH64_MOD_LSL;
+ info->shifter.amount = get_operand_specific_data (self);
+ info->shifter.operator_present = (info->shifter.amount != 0);
+ info->shifter.amount_present = (info->shifter.amount != 0);
+ return 1;
+}
+
+/* Decode an SVE address [X<n>, Z<m>.<T>, (S|U)XTW {#<shift>}], where
+ <shift> is SELF's operand-dependent value. fields[0] specifies the
+ base register field, fields[1] specifies the offset register field and
+ fields[2] is a single-bit field that selects SXTW over UXTW. */
+int
+aarch64_ext_sve_addr_rz_xtw (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ info->addr.base_regno = extract_field (self->fields[0], code, 0);
+ info->addr.offset.regno = extract_field (self->fields[1], code, 0);
+ info->addr.offset.is_reg = TRUE;
+ info->addr.writeback = FALSE;
+ info->addr.preind = TRUE;
+ if (extract_field (self->fields[2], code, 0))
+ info->shifter.kind = AARCH64_MOD_SXTW;
+ else
+ info->shifter.kind = AARCH64_MOD_UXTW;
+ info->shifter.amount = get_operand_specific_data (self);
+ info->shifter.operator_present = TRUE;
+ info->shifter.amount_present = (info->shifter.amount != 0);
+ return 1;
+}
+
+/* Decode an SVE address [Z<n>.<T>, #<imm5> << <shift>], where <imm5> is a
+ 5-bit unsigned number and where <shift> is SELF's operand-dependent value.
+ fields[0] specifies the base register field. */
+int
+aarch64_ext_sve_addr_zi_u5 (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ int offset = extract_field (FLD_imm5, code, 0);
+ return aarch64_ext_sve_addr_reg_imm (self, info, code, offset);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, <modifier> {#<msz>}}],
+ where <modifier> is given by KIND and where <msz> is a 2-bit unsigned
+ number. fields[0] specifies the base register field and fields[1]
+ specifies the offset register field. */
+static int
+aarch64_ext_sve_addr_zz (const aarch64_operand *self, aarch64_opnd_info *info,
+ aarch64_insn code, enum aarch64_modifier_kind kind)
+{
+ info->addr.base_regno = extract_field (self->fields[0], code, 0);
+ info->addr.offset.regno = extract_field (self->fields[1], code, 0);
+ info->addr.offset.is_reg = TRUE;
+ info->addr.writeback = FALSE;
+ info->addr.preind = TRUE;
+ info->shifter.kind = kind;
+ info->shifter.amount = extract_field (FLD_SVE_msz, code, 0);
+ info->shifter.operator_present = (kind != AARCH64_MOD_LSL
+ || info->shifter.amount != 0);
+ info->shifter.amount_present = (info->shifter.amount != 0);
+ return 1;
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>{, LSL #<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+int
+aarch64_ext_sve_addr_zz_lsl (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_LSL);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, SXTW {#<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+int
+aarch64_ext_sve_addr_zz_sxtw (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_SXTW);
+}
+
+/* Decode an SVE address [Z<n>.<T>, Z<m>.<T>, UXTW {#<msz>}], where
+ <msz> is a 2-bit unsigned number. fields[0] specifies the base register
+ field and fields[1] specifies the offset register field. */
+int
+aarch64_ext_sve_addr_zz_uxtw (const aarch64_operand *self,
+ aarch64_opnd_info *info, aarch64_insn code,
+ const aarch64_inst *inst ATTRIBUTE_UNUSED)
+{
+ return aarch64_ext_sve_addr_zz (self, info, code, AARCH64_MOD_UXTW);
+}
+
/* Decode Zn[MM], where MM has a 7-bit triangular encoding. The fields
array specifies which field to use for Zn. MM is encoded in the
concatenation of imm5 and SVE_tszh, with imm5 being the less