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
+aarch64_insn
extract_fields (aarch64_insn code, aarch64_insn mask, ...)
{
uint32_t num;
switch (simd_size)
{
case 2: imm = (imm << 2) | imm;
+ /* Fall through. */
case 4: imm = (imm << 4) | imm;
+ /* Fall through. */
case 8: imm = (imm << 8) | imm;
+ /* Fall through. */
case 16: imm = (imm << 16) | imm;
+ /* Fall through. */
case 32: imm = (imm << 32) | imm;
+ /* Fall through. */
case 64: break;
default: assert (0); return 0;
}
static int
do_misc_decoding (aarch64_inst *inst)
{
+ unsigned int value;
switch (inst->opcode->op)
{
case OP_FCVT:
return decode_fcvt (inst);
+
case OP_FCVTN:
case OP_FCVTN2:
case OP_FCVTL:
case OP_FCVTL2:
return decode_asimd_fcvt (inst);
+
case OP_FCVTXN_S:
return decode_asisd_fcvtxn (inst);
+
+ case OP_MOV_P_P:
+ case OP_MOVS_P_P:
+ value = extract_field (FLD_SVE_Pn, inst->value, 0);
+ return (value == extract_field (FLD_SVE_Pm, inst->value, 0)
+ && value == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
+
+ case OP_MOV_Z_P_Z:
+ return (extract_field (FLD_SVE_Zd, inst->value, 0)
+ == extract_field (FLD_SVE_Zm_16, inst->value, 0));
+
+ case OP_MOV_Z_V:
+ /* Index must be zero. */
+ value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
+ return value == 1 || value == 2 || value == 4 || value == 8;
+
+ case OP_MOV_Z_Z:
+ return (extract_field (FLD_SVE_Zn, inst->value, 0)
+ == extract_field (FLD_SVE_Zm_16, inst->value, 0));
+
+ case OP_MOV_Z_Zi:
+ /* Index must be nonzero. */
+ value = extract_fields (inst->value, 0, 2, FLD_SVE_tszh, FLD_imm5);
+ return value != 1 && value != 2 && value != 4 && value != 8;
+
+ case OP_MOVM_P_P_P:
+ return (extract_field (FLD_SVE_Pd, inst->value, 0)
+ == extract_field (FLD_SVE_Pm, inst->value, 0));
+
+ case OP_MOVZS_P_P_P:
+ case OP_MOVZ_P_P_P:
+ return (extract_field (FLD_SVE_Pn, inst->value, 0)
+ == extract_field (FLD_SVE_Pm, inst->value, 0));
+
+ case OP_NOTS_P_P_P_Z:
+ case OP_NOT_P_P_P_Z:
+ return (extract_field (FLD_SVE_Pm, inst->value, 0)
+ == extract_field (FLD_SVE_Pg4_10, inst->value, 0));
+
default:
return 0;
}
}
}
+/* Set NAME to a copy of INST's mnemonic with the "." suffix removed. */
+
+static void
+remove_dot_suffix (char *name, const aarch64_inst *inst)
+{
+ char *ptr;
+ size_t len;
+
+ ptr = strchr (inst->opcode->name, '.');
+ assert (ptr && inst->cond);
+ len = ptr - inst->opcode->name;
+ assert (len < 8);
+ strncpy (name, inst->opcode->name, len);
+ name[len] = '\0';
+}
+
/* Print the instruction mnemonic name. */
static void
/* For instructions that are truly conditionally executed, e.g. b.cond,
prepare the full mnemonic name with the corresponding condition
suffix. */
- char name[8], *ptr;
- size_t len;
-
- ptr = strchr (inst->opcode->name, '.');
- assert (ptr && inst->cond);
- len = ptr - inst->opcode->name;
- assert (len < 8);
- strncpy (name, inst->opcode->name, len);
- name [len] = '\0';
+ char name[8];
+
+ remove_dot_suffix (name, inst);
(*info->fprintf_func) (info->stream, "%s.%s", name, inst->cond->names[0]);
}
else
(*info->fprintf_func) (info->stream, "%s", inst->opcode->name);
}
+/* Decide whether we need to print a comment after the operands of
+ instruction INST. */
+
+static void
+print_comment (const aarch64_inst *inst, struct disassemble_info *info)
+{
+ if (inst->opcode->flags & F_COND)
+ {
+ char name[8];
+ unsigned int i, num_conds;
+
+ remove_dot_suffix (name, inst);
+ num_conds = ARRAY_SIZE (inst->cond->names);
+ for (i = 1; i < num_conds && inst->cond->names[i]; ++i)
+ (*info->fprintf_func) (info->stream, "%s %s.%s",
+ i == 1 ? " //" : ",",
+ name, inst->cond->names[i]);
+ }
+}
+
/* Print the instruction according to *INST. */
static void
{
print_mnemonic_name (inst, info);
print_operands (pc, inst->opcode, inst->operands, info);
+ print_comment (inst, info);
}
/* Entry-point of the instruction disassembler and printer. */