0 },
{ "750cl", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
, 0 },
+ { "gekko", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
+ , 0 },
+ { "broadway", PPC_OPCODE_PPC | PPC_OPCODE_750 | PPC_OPCODE_PPCPS
+ , 0 },
{ "821", PPC_OPCODE_PPC | PPC_OPCODE_860,
0 },
{ "850", PPC_OPCODE_PPC | PPC_OPCODE_860,
case bfd_mach_ppc_601:
dialect = ppc_parse_cpu (dialect, &sticky, "601");
break;
+ case bfd_mach_ppc_750:
+ dialect = ppc_parse_cpu (dialect, &sticky, "750cl");
+ break;
case bfd_mach_ppc_a35:
case bfd_mach_ppc_rs64ii:
case bfd_mach_ppc_rs64iii:
POWERPC_DIALECT(info) = dialect;
}
-#define PPC_OPCD_SEGS 64
-static unsigned short powerpc_opcd_indices[PPC_OPCD_SEGS+1];
-#define VLE_OPCD_SEGS 32
-static unsigned short vle_opcd_indices[VLE_OPCD_SEGS+1];
-#define SPE2_OPCD_SEGS 13
-static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS+1];
+#define PPC_OPCD_SEGS (1 + PPC_OP (-1))
+static unsigned short powerpc_opcd_indices[PPC_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)))
+static unsigned short spe2_opcd_indices[SPE2_OPCD_SEGS + 1];
/* Calculate opcode table indices to speed up disassembly,
and init dialect. */
uint64_t insn, ppc_cpu_t dialect)
{
int64_t value;
- int invalid;
+ int invalid = 0;
/* Extract the value from the instruction. */
if (operand->extract)
value = (*operand->extract) (insn, dialect, &invalid);
uint64_t insn, ppc_cpu_t dialect)
{
const struct powerpc_operand *operand;
+ int num_optional;
- for (; *opindex != 0; opindex++)
+ for (num_optional = 0; *opindex != 0; opindex++)
{
operand = &powerpc_operands[*opindex];
- if ((operand->flags & PPC_OPERAND_NEXT) != 0
- || ((operand->flags & PPC_OPERAND_OPTIONAL) != 0
- && operand_value_powerpc (operand, insn, dialect) !=
- ppc_optional_operand_value (operand)))
+ if ((operand->flags & PPC_OPERAND_NEXT) != 0)
return 0;
+ if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
+ {
+ /* Negative count is used as a flag to extract function. */
+ --num_optional;
+ if (operand_value_powerpc (operand, insn, dialect)
+ != ppc_optional_operand_value (operand, insn, dialect,
+ num_optional))
+ return 0;
+ }
}
return 1;
int status;
uint64_t insn;
const struct powerpc_opcode *opcode;
- bfd_boolean insn_is_short;
+ int insn_length = 4; /* Assume we have a normal 4-byte instruction. */
status = (*info->read_memory_func) (memaddr, buffer, 4, info);
+
+ /* The final instruction may be a 2-byte VLE insn. */
+ 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;
+ status = (*info->read_memory_func) (memaddr, buffer, 2, info);
+ }
+
if (status != 0)
{
- /* The final instruction may be a 2-byte VLE insn. */
- if ((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;
- status = (*info->read_memory_func) (memaddr, buffer, 2, info);
- if (status != 0)
- {
- (*info->memory_error_func) (status, memaddr, info);
- return -1;
- }
- }
- else
- {
- (*info->memory_error_func) (status, memaddr, info);
- return -1;
- }
+ (*info->memory_error_func) (status, memaddr, info);
+ return -1;
}
if (bigendian)
/* Get the major opcode of the insn. */
opcode = NULL;
- insn_is_short = FALSE;
if ((dialect & PPC_OPCODE_VLE) != 0)
{
opcode = lookup_vle (insn);
- if (opcode != NULL)
- insn_is_short = PPC_OP_SE_VLE(opcode->mask);
+ if (opcode != NULL && PPC_OP_SE_VLE (opcode->mask))
+ {
+ /* The operands will be fetched out of the 16-bit instruction. */
+ insn >>= 16;
+ insn_length = 2;
+ }
}
if (opcode == NULL && (dialect & PPC_OPCODE_SPE2) != 0)
opcode = lookup_spe2 (insn);
else
(*info->fprintf_func) (info->stream, "%s", opcode->name);
- if (insn_is_short)
- /* The operands will be fetched out of the 16-bit instruction. */
- insn >>= 16;
-
/* Now extract and print the operands. */
need_comma = 0;
need_paren = 0;
operand = powerpc_operands + *opindex;
- /* Operands that are marked FAKE are simply ignored. We
- already made sure that the extract function considered
- the instruction to be valid. */
- if ((operand->flags & PPC_OPERAND_FAKE) != 0)
- continue;
-
/* If all of the optional operands have the value zero,
then don't print any of them. */
if ((operand->flags & PPC_OPERAND_OPTIONAL) != 0)
}
}
- /* We have found and printed an instruction.
- If it was a short VLE instruction we have more to do. */
- if (insn_is_short)
- {
- memaddr += 2;
- return 2;
- }
- else
- /* Otherwise, return. */
- return 4;
+ /* We have found and printed an instruction. */
+ return insn_length;
}
/* We could not find a match. */
return 4;
}
-const disasm_options_t *
+const disasm_options_and_args_t *
disassembler_options_powerpc (void)
{
- static disasm_options_t *opts = NULL;
+ static disasm_options_and_args_t *opts_and_args;
- if (opts == NULL)
+ if (opts_and_args == NULL)
{
size_t i, num_options = ARRAY_SIZE (ppc_opts);
- opts = XNEW (disasm_options_t);
+ disasm_options_t *opts;
+
+ opts_and_args = XNEW (disasm_options_and_args_t);
+ opts_and_args->args = NULL;
+
+ opts = &opts_and_args->options;
opts->name = XNEWVEC (const char *, num_options + 1);
+ opts->description = NULL;
+ opts->arg = NULL;
for (i = 0; i < num_options; i++)
opts->name[i] = ppc_opts[i].opt;
/* The array we return must be NULL terminated. */
opts->name[i] = NULL;
- opts->description = NULL;
}
- return opts;
+ return opts_and_args;
}
void