ppc/svp64: disassemble branch mode
authorDmitry Selyutin <ghostmansd@gmail.com>
Sun, 28 May 2023 22:04:57 +0000 (01:04 +0300)
committerDmitry Selyutin <ghostmansd@gmail.com>
Mon, 7 Aug 2023 20:02:38 +0000 (23:02 +0300)
opcodes/ppc-svp64-dis.c

index d34748bcf5dc9cc4ef93f507f5bc04947967f491..05a22f2fdf7884391de0e30df9814370ec3eb5bb 100644 (file)
@@ -708,6 +708,104 @@ svp64_spec_crop_ff5 (const struct svp64_ctx *svp64,
   return len;
 }
 
+static size_t
+svp64_spec_branch (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  size_t len = 0;
+  uint64_t ALL = svp64_insn_get_prefix_rm_branch_ALL (&svp64->insn);
+  uint64_t SNZ = svp64_insn_get_prefix_rm_branch_SNZ (&svp64->insn);
+  uint64_t SL = svp64_insn_get_prefix_rm_branch_SL (&svp64->insn);
+  uint64_t SLu = svp64_insn_get_prefix_rm_branch_SLu (&svp64->insn);
+  uint64_t LRu = svp64_insn_get_prefix_rm_branch_LRu (&svp64->insn);
+  uint64_t sz = svp64_insn_get_prefix_rm_branch_sz (&svp64->insn);
+  uint64_t CR = svp64_insn_get_prefix_rm_mmode (&svp64->insn);
+  uint64_t m = svp64_insn_get_prefix_rm_mask (&svp64->insn);
+
+  if (ALL)
+    len += svp64_spec_printf (info, "all");
+
+  len += svp64_spec_dz_sz_zz_SNZ (info, false, sz, SNZ);
+
+  if (SL)
+    len += svp64_spec_printf (info, "sl");
+  if (SLu)
+    len += svp64_spec_printf (info, "slu");
+  if (LRu)
+    len += svp64_spec_printf (info, "lru");
+
+  if (m)
+    len += svp64_spec_printf (info, "m=%s", svp64_predicate (CR, m));
+
+  len += svp64_spec_vec (svp64, info);
+
+  return len;
+}
+
+static size_t
+svp64_spec_branch_VSb_VLi (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  uint64_t VSb = svp64_insn_get_prefix_rm_branch_vls_VSb (&svp64->insn);
+  uint64_t VLi = svp64_insn_get_prefix_rm_branch_vls_VLi (&svp64->insn);
+  static const char *const table[] = {"vs", "vsi", "vsb", "vsbi"};
+
+  return svp64_spec_printf (info, table[((VSb << 1) | (VLi << 0))]);
+}
+
+static size_t
+svp64_spec_branch_CTi (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  uint64_t CTi = svp64_insn_get_prefix_rm_branch_ctr_CTi (&svp64->insn);
+
+  return svp64_spec_printf (info, (CTi ? "cti" : "ctr"));
+}
+
+static size_t
+svp64_spec_branch_simple (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  return svp64_spec_branch (svp64, info);
+}
+
+static size_t
+svp64_spec_branch_vls (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  size_t len = 0;
+
+  len += svp64_spec_branch_VSb_VLi (svp64, info);
+  len += svp64_spec_branch (svp64, info);
+
+  return len;
+}
+
+static size_t
+svp64_spec_branch_ctr (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  size_t len = 0;
+
+  len += svp64_spec_branch_CTi (svp64, info);
+  len += svp64_spec_branch (svp64, info);
+
+  return len;
+}
+
+static size_t
+svp64_spec_branch_ctrvls (const struct svp64_ctx *svp64,
+  struct disassemble_info *info)
+{
+  size_t len = 0;
+
+  len += svp64_spec_branch_VSb_VLi (svp64, info);
+  len += svp64_spec_branch_CTi (svp64, info);
+  len += svp64_spec_branch (svp64, info);
+
+  return len;
+}
+
 static size_t
 svp64_print_spec (const struct svp64_ctx *svp64,
   struct disassemble_info *info)
@@ -738,11 +836,18 @@ svp64_print_spec (const struct svp64_ctx *svp64,
     {0x21, 0x21, svp64_spec_crop_ff3},       /* failfirst, 3-bit CR */
     {0x20, 0x20, svp64_spec_crop_ff5},       /* failfirst, 5-bit CR */
   };
+  static const struct svp64_spec_subtable branch[] = {
+    {0x00, 0x03, svp64_spec_branch_simple},   /* simple              */
+    {0x01, 0x03, svp64_spec_branch_vls},      /* VLset               */
+    {0x02, 0x03, svp64_spec_branch_ctr},      /* CTR mode            */
+    {0x03, 0x03, svp64_spec_branch_ctrvls},   /* CTR+VLset mode      */
+  };
   static const struct svp64_spec_table tables[] = {
     [SVP64_MODE_NORMAL] = {normal, ARRAY_SIZE (normal)},
     [SVP64_MODE_LDST_IMM] = {ldst_imm, ARRAY_SIZE (ldst_imm)},
     [SVP64_MODE_LDST_IDX] = {ldst_idx, ARRAY_SIZE (ldst_idx)},
     [SVP64_MODE_CROP] = {crop, ARRAY_SIZE (crop)},
+    [SVP64_MODE_BRANCH] = {branch, ARRAY_SIZE (branch)},
   };
   const struct svp64_spec_table *table = &tables[svp64->desc->mode];
   uint64_t mode = svp64_insn_get_prefix_rm_mode (&svp64->insn);