ppc/svp64: disassemble SVP64 operands
[binutils-gdb.git] / opcodes / ppc-svp64-dis.c
index 90e37726d889558337fab8a4373893bd81c22093..687078e2ff5ad369674027f3e9236272aac881d1 100644 (file)
@@ -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;
+}