#include "opcode/ppc.h"
#include "libiberty.h"
+#include "ppc-svp64-dis.c"
+
/* This file provides several disassembler functions, all of which use
the disassembler interface defined in dis-asm.h. Several functions
are provided because this file handles disassembly for the PowerPC
break;
}
}
+
+ svp64_disassemble_init ();
}
powerpc_init_dialect (info);
/* Get the major opcode of the insn. */
opcode = NULL;
- if ((dialect & PPC_OPCODE_POWER10) != 0
+ if ((dialect & (PPC_OPCODE_POWER10 | PPC_OPCODE_SVP64)) != 0
&& PPC_OP (insn) == 0x1)
{
uint64_t temp_insn, suffix;
+
status = (*info->read_memory_func) (memaddr + 4, buffer, 4, info);
if (status == 0)
{
else
suffix = bfd_getl32 (buffer);
temp_insn = (insn << 32) | suffix;
- opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
+
+ if ((dialect & PPC_OPCODE_SVP64) != 0)
+ {
+ opcode = svp64_lookup (temp_insn, dialect);
+ if (opcode != NULL)
+ {
+ insn = temp_insn;
+ insn_length = 8;
+ }
+ }
+
+ if (opcode == NULL)
+ opcode = lookup_prefix (temp_insn, dialect & ~PPC_OPCODE_ANY);
if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
opcode = lookup_prefix (temp_insn, dialect);
if (opcode != NULL)
--- /dev/null
+/* ppc-dis.c -- Disassemble PowerPC instructions
+ Copyright (C) 1994-2022 Free Software Foundation, Inc.
+ Written by Dmitry Selyutin (ghostmansd).
+ Sponsored by NLnet and NGI POINTER under EU Grants 871528 and 957073.
+
+ This file is part of the GNU opcodes library.
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ It is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this file; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include <stdlib.h>
+
+#define SVP64_RECORD_SEGS (1 + SVP64_OP (-1))
+static unsigned short svp64_record_indices[SVP64_RECORD_SEGS + 1];
+
+static const struct powerpc_opcode *
+lookup_powerpc (uint64_t insn, ppc_cpu_t dialect);
+
+static void
+svp64_disassemble_init (void)
+{
+ size_t seg;
+ size_t idx;
+
+ for (seg = 0, idx = 0; seg <= SVP64_RECORD_SEGS; seg++)
+ {
+ svp64_record_indices[seg] = idx;
+ for (; idx < svp64_nr_records; idx++)
+ {
+ const struct svp64_opcode *opcode;
+ const struct svp64_opcode *opcode_end;
+
+ opcode = svp64_records[idx].opcodes;
+ opcode_end = (opcode + svp64_records[idx].nr_opcodes);
+
+ if (seg < SVP64_OP (opcode->value))
+ break;
+
+ /* Check that the segment doesn't break in the middle. */
+ for (; opcode < opcode_end; ++opcode)
+ {
+ if (seg < SVP64_OP (opcode->value))
+ abort ();
+ }
+ }
+ }
+}
+
+static const struct svp64_record *
+svp64_lookup_record (uint32_t insn,
+ const struct svp64_record *start,
+ const struct svp64_record *end)
+{
+ const struct svp64_record *record;
+
+ for (record = start; record < end; ++record)
+ {
+ const struct svp64_opcode *opcode;
+ const struct svp64_opcode *opcode_end;
+
+ opcode = record->opcodes;
+ opcode_end = (opcode + record->nr_opcodes);
+ for (; opcode < opcode_end; ++opcode)
+ {
+ if ((opcode->value & opcode->mask) ==
+ (insn & opcode->mask))
+ return record;
+ }
+ }
+
+ return NULL;
+}
+
+static const struct powerpc_opcode *
+svp64_lookup (uint64_t insn, ppc_cpu_t dialect)
+{
+ uint32_t suffix;
+ unsigned long op;
+ const struct powerpc_opcode *opcode;
+ const struct svp64_record *record;
+ const struct svp64_record *record_start;
+ const struct svp64_record *record_end;
+ struct svp64_insn svp64_insn = {insn};
+
+ if ((svp64_insn_get_prefix_po (&svp64_insn) != 0x1) ||
+ (svp64_insn_get_prefix_id (&svp64_insn) != 0x3))
+ return NULL;
+
+ suffix = (uint32_t)svp64_insn_get_suffix (&svp64_insn);
+ opcode = lookup_powerpc (suffix, dialect & ~PPC_OPCODE_ANY);
+ if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+ opcode = lookup_powerpc (suffix, dialect);
+ if (opcode == NULL)
+ return NULL;
+
+ op = SVP64_OP (suffix);
+ record_start = svp64_records + svp64_record_indices[op];
+ record_end = (svp64_records + svp64_record_indices[op + 1]);
+ record = svp64_lookup_record (suffix, record_start, record_end);
+ if (record == record_end)
+ return NULL;
+
+ return opcode;
+}