/* ppc-dis.c -- Disassemble PowerPC instructions
- Copyright (C) 1994-2019 Free Software Foundation, Inc.
+ Copyright (C) 1994-2020 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Cygnus Support
This file is part of the GNU opcodes library.
{
/* Stash the result of parsing disassembler_options here. */
ppc_cpu_t dialect;
-} private;
+};
#define POWERPC_DIALECT(INFO) \
(((struct dis_private *) ((INFO)->private_data))->dialect)
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
| PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
0 },
+ { "power10", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
+ | PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
+ | PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
+ | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
+ 0 },
{ "future", (PPC_OPCODE_PPC | PPC_OPCODE_ISEL | PPC_OPCODE_64
| PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6
| PPC_OPCODE_POWER7 | PPC_OPCODE_POWER8 | PPC_OPCODE_POWER9
- | PPC_OPCODE_POWERXX | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
+ | PPC_OPCODE_POWER10 | PPC_OPCODE_ALTIVEC | PPC_OPCODE_VSX),
0 },
{ "ppc", PPC_OPCODE_PPC,
0 },
{
ppc_cpu_t dialect = 0;
- dialect = POWERPC_DIALECT (info);
+ if (info->private_data)
+ dialect = POWERPC_DIALECT (info);
/* Disassemble according to the section headers flags for VLE-mode. */
if (dialect & PPC_OPCODE_VLE
struct dis_private *priv = calloc (sizeof (*priv), 1);
if (priv == NULL)
- priv = &private;
+ return;
switch (info->mach)
{
break;
default:
if (info->arch == bfd_arch_powerpc)
- dialect = ppc_parse_cpu (dialect, &sticky, "power9") | PPC_OPCODE_ANY;
+ dialect = ppc_parse_cpu (dialect, &sticky, "power10") | PPC_OPCODE_ANY;
else
dialect = ppc_parse_cpu (dialect, &sticky, "pwr");
break;
#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS + 1];
#define PREFIX_OPCD_SEGS (1 + PPC_PREFIX_SEG (-1))
-static unsigned short prefix_opcd_indices[PPC_OPCD_SEGS+1];
+static unsigned short prefix_opcd_indices[PREFIX_OPCD_SEGS + 1];
#define VLE_OPCD_SEGS (1 + VLE_OP_TO_SEG (VLE_OP (-1, 0xffff)))
static unsigned short vle_opcd_indices[VLE_OPCD_SEGS + 1];
#define SPE2_OPCD_SEGS (1 + SPE2_XOP_TO_SEG (SPE2_XOP (-1)))
if (status != 0 && (dialect & PPC_OPCODE_VLE) != 0)
{
/* Clear buffer so unused bytes will not have garbage in them. */
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0;
+ buffer[2] = buffer[3] = 0;
status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ insn_length = 2;
}
if (status != 0)
/* Get the major opcode of the insn. */
opcode = NULL;
- if ((dialect & PPC_OPCODE_POWERXX) != 0
+ if ((dialect & PPC_OPCODE_POWER10) != 0
&& PPC_OP (insn) == 0x1)
{
uint64_t temp_insn, suffix;
insn_length = 2;
}
}
- if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
- opcode = lookup_spe2 (insn);
- if (opcode == NULL)
- opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
- if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
- opcode = lookup_powerpc (insn, dialect);
+ if (opcode == NULL && insn_length == 4)
+ {
+ if ((dialect & PPC_OPCODE_SPE2) != 0)
+ opcode = lookup_spe2 (insn);
+ if (opcode == NULL)
+ opcode = lookup_powerpc (insn, dialect & ~PPC_OPCODE_ANY);
+ if (opcode == NULL && (dialect & PPC_OPCODE_ANY) != 0)
+ opcode = lookup_powerpc (insn, dialect);
+ }
if (opcode != NULL)
{
need_paren
} op_separator;
bfd_boolean skip_optional;
- int spaces;
+ int blanks;
(*info->fprintf_func) (info->stream, "%s", opcode->name);
/* gdb fprintf_func doesn't return count printed. */
- spaces = 8 - strlen (opcode->name);
- if (spaces <= 0)
- spaces = 1;
+ blanks = 8 - strlen (opcode->name);
+ if (blanks <= 0)
+ blanks = 1;
/* Now extract and print the operands. */
- op_separator = spaces;
+ op_separator = blanks;
skip_optional = FALSE;
for (opindex = opcode->operands; *opindex != 0; opindex++)
{
(*info->fprintf_func) (info->stream, "v%" PRId64, value);
else if ((operand->flags & PPC_OPERAND_VSR) != 0)
(*info->fprintf_func) (info->stream, "vs%" PRId64, value);
+ else if ((operand->flags & PPC_OPERAND_ACC) != 0)
+ (*info->fprintf_func) (info->stream, "a%" PRId64, value);
else if ((operand->flags & PPC_OPERAND_RELATIVE) != 0)
(*info->print_address_func) (memaddr + value, info);
else if ((operand->flags & PPC_OPERAND_ABSOLUTE) != 0)
}
/* We could not find a match. */
- (*info->fprintf_func) (info->stream, ".long 0x%" PRIx64, insn);
-
- return 4;
+ if (insn_length == 4)
+ (*info->fprintf_func) (info->stream, ".long 0x%x",
+ (unsigned int) insn);
+ else
+ (*info->fprintf_func) (info->stream, ".word 0x%x",
+ (unsigned int) insn >> 16);
+ return insn_length;
}
const disasm_options_and_args_t *