From 9087e63092119e674ef28a6731c55803413694d0 Mon Sep 17 00:00:00 2001 From: Dmitry Selyutin Date: Thu, 22 Sep 2022 13:48:36 +0300 Subject: [PATCH] ppc/svp64: disassemble SVP64 operands --- opcodes/ppc-dis.c | 40 ++++++++++++++++----- opcodes/ppc-svp64-dis.c | 78 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 109 insertions(+), 9 deletions(-) diff --git a/opcodes/ppc-dis.c b/opcodes/ppc-dis.c index aa8f9ea4c64..0d17c7a3bad 100644 --- a/opcodes/ppc-dis.c +++ b/opcodes/ppc-dis.c @@ -906,6 +906,7 @@ print_insn_powerpc_opcode (struct disassemble_info *info, d34 = 0; for (opindex = opcode->operands; *opindex != 0; opindex++) { + bool vector; int64_t value; operand = powerpc_operands + *opindex; @@ -923,7 +924,13 @@ print_insn_powerpc_opcode (struct disassemble_info *info, continue; } + vector = false; value = operand_value_powerpc (operand, insn, dialect); + if (svp64) + { + value = svp64_operand_value (svp64, + value, *opindex, operand->flags, &vector); + } if (op_separator == need_comma) (*info->fprintf_styled_func) (info->stream, dis_style_text, ","); @@ -937,10 +944,12 @@ print_insn_powerpc_opcode (struct disassemble_info *info, if ((operand->flags & PPC_OPERAND_GPR) != 0 || ((operand->flags & PPC_OPERAND_GPR_0) != 0 && value != 0)) (*info->fprintf_styled_func) (info->stream, dis_style_register, - "r%" PRId64, value); + "%sr%" PRId64, + (vector ? "*" : ""), value); else if ((operand->flags & PPC_OPERAND_FPR) != 0) (*info->fprintf_styled_func) (info->stream, dis_style_register, - "f%" PRId64, value); + "%sf%" PRId64, + (vector ? "*" : ""), value); else if ((operand->flags & PPC_OPERAND_VR) != 0) (*info->fprintf_styled_func) (info->stream, dis_style_register, "v%" PRId64, value); @@ -982,13 +991,26 @@ print_insn_powerpc_opcode (struct disassemble_info *info, cc = value & 3; if (cr != 0) { - (*info->fprintf_styled_func) (info->stream, dis_style_text, - "4*"); - (*info->fprintf_styled_func) (info->stream, - dis_style_register, - "cr%d", cr); - (*info->fprintf_styled_func) (info->stream, dis_style_text, - "+"); + if (svp64) + { + (*info->fprintf_styled_func) (info->stream, + dis_style_register, + "%scr%d", + (vector ? "*" : ""), + cr); + (*info->fprintf_styled_func) (info->stream, dis_style_text, + "."); + } + else + { + (*info->fprintf_styled_func) (info->stream, dis_style_text, + "4*"); + (*info->fprintf_styled_func) (info->stream, + dis_style_register, + "cr%d", cr); + (*info->fprintf_styled_func) (info->stream, dis_style_text, + "+"); + } } (*info->fprintf_styled_func) (info->stream, diff --git a/opcodes/ppc-svp64-dis.c b/opcodes/ppc-svp64-dis.c index 90e37726d88..687078e2ff5 100644 --- a/opcodes/ppc-svp64-dis.c +++ b/opcodes/ppc-svp64-dis.c @@ -118,3 +118,81 @@ svp64_lookup (uint64_t insn, ppc_cpu_t dialect, return opcode; } + +static int64_t +svp64_operand_value_common (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, bool *vector, + int vector_shift, int scalar_shift, int spec_shift) +{ + uint64_t spec; + const struct svp64_extra_desc *desc; + + desc = svp64_extra_desc (svp64->desc, opindex); + spec = (*desc->get) (&svp64->insn); + + if (spec == 0) + return value; + + *vector = (((spec >> 2) & 1) != 0); + if (svp64->desc->etype == SVP64_ETYPE_EXTRA2) + spec <<= 1; + + spec = (spec & 0x3); + + if (*vector) + value = ((value << vector_shift) | (spec << spec_shift)); + else + value = ((spec << scalar_shift) | value); + + return value; +} + +static int64_t +svp64_operand_value_gpr (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, bool *vector) +{ + return svp64_operand_value_common (svp64, value, opindex, vector, 2, 5, 0); +} + +static int64_t +svp64_operand_value_fpr (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, bool *vector) +{ + return svp64_operand_value_common (svp64, value, opindex, vector, 2, 5, 0); +} + +static int64_t +svp64_operand_value_cr_reg (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, bool *vector) +{ + return svp64_operand_value_common (svp64, value, opindex, vector, 4, 3, 2); +} + +static int64_t +svp64_operand_value_cr_bit (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, bool *vector) +{ + uint64_t bits = (value & 0x3); + + value >>= 2; + value = svp64_operand_value_common (svp64, value, opindex, vector, 4, 3, 2); + value = ((value << 2) | bits); + + return value; +} + +static int64_t +svp64_operand_value (const struct svp64_ctx *svp64, + int64_t value, ppc_opindex_t opindex, uint64_t flags, bool *vector) +{ + if (flags & (PPC_OPERAND_GPR | PPC_OPERAND_GPR_0)) + return svp64_operand_value_gpr (svp64, value, opindex, vector); + else if (flags & PPC_OPERAND_FPR) + return svp64_operand_value_fpr (svp64, value, opindex, vector); + else if (flags & PPC_OPERAND_CR_REG) + return svp64_operand_value_cr_reg (svp64, value, opindex, vector); + else if (flags & PPC_OPERAND_CR_BIT) + return svp64_operand_value_cr_bit (svp64, value, opindex, vector); + else + return value; +} -- 2.30.2