+ if ((operand->flags & PPC_OPERAND_NEXT) != 0)
+ return FALSE;
+ 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 FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/* Find a match for INSN in the opcode table, given machine DIALECT. */
+
+static const struct powerpc_opcode *
+lookup_powerpc (uint64_t insn, ppc_cpu_t dialect)
+{
+ const struct powerpc_opcode *opcode, *opcode_end, *last;
+ unsigned long op;
+
+ /* Get the major opcode of the instruction. */
+ op = PPC_OP (insn);
+
+ /* Find the first match in the opcode table for this major opcode. */
+ opcode_end = powerpc_opcodes + powerpc_opcd_indices[op + 1];
+ last = NULL;
+ for (opcode = powerpc_opcodes + powerpc_opcd_indices[op];
+ opcode < opcode_end;
+ ++opcode)
+ {
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+
+ if ((insn & opcode->mask) != opcode->opcode
+ || ((dialect & PPC_OPCODE_ANY) == 0
+ && ((opcode->flags & dialect) == 0
+ || (opcode->deprecated & dialect) != 0)))
+ continue;
+
+ /* Check validity of operands. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, dialect, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ if ((dialect & PPC_OPCODE_RAW) == 0)
+ return opcode;
+
+ /* The raw machine insn is one that is not a specialization. */
+ if (last == NULL
+ || (last->mask & ~opcode->mask) != 0)
+ last = opcode;
+ }
+
+ return last;
+}
+
+/* Find a match for INSN in the PREFIX opcode table. */
+
+static const struct powerpc_opcode *
+lookup_prefix (uint64_t insn, ppc_cpu_t dialect)
+{
+ const struct powerpc_opcode *opcode, *opcode_end, *last;
+ unsigned long seg;
+
+ /* Get the opcode segment of the instruction. */
+ seg = PPC_PREFIX_SEG (insn);
+
+ /* Find the first match in the opcode table for this major opcode. */
+ opcode_end = prefix_opcodes + prefix_opcd_indices[seg + 1];
+ last = NULL;
+ for (opcode = prefix_opcodes + prefix_opcd_indices[seg];
+ opcode < opcode_end;
+ ++opcode)
+ {
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+
+ if ((insn & opcode->mask) != opcode->opcode
+ || ((dialect & PPC_OPCODE_ANY) == 0
+ && ((opcode->flags & dialect) == 0
+ || (opcode->deprecated & dialect) != 0)))
+ continue;
+
+ /* Check validity of operands. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; opindex++)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, dialect, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ if ((dialect & PPC_OPCODE_RAW) == 0)
+ return opcode;
+
+ /* The raw machine insn is one that is not a specialization. */
+ if (last == NULL
+ || (last->mask & ~opcode->mask) != 0)
+ last = opcode;
+ }
+
+ return last;
+}
+
+/* Find a match for INSN in the VLE opcode table. */
+
+static const struct powerpc_opcode *
+lookup_vle (uint64_t insn)
+{
+ const struct powerpc_opcode *opcode;
+ const struct powerpc_opcode *opcode_end;
+ unsigned op, seg;
+
+ op = PPC_OP (insn);
+ if (op >= 0x20 && op <= 0x37)
+ {
+ /* This insn has a 4-bit opcode. */
+ op &= 0x3c;
+ }
+ seg = VLE_OP_TO_SEG (op);
+
+ /* Find the first match in the opcode table for this major opcode. */
+ opcode_end = vle_opcodes + vle_opcd_indices[seg + 1];
+ for (opcode = vle_opcodes + vle_opcd_indices[seg];
+ opcode < opcode_end;
+ ++opcode)
+ {
+ uint64_t table_opcd = opcode->opcode;
+ uint64_t table_mask = opcode->mask;
+ bfd_boolean table_op_is_short = PPC_OP_SE_VLE(table_mask);
+ uint64_t insn2;
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+
+ insn2 = insn;
+ if (table_op_is_short)
+ insn2 >>= 16;
+ if ((insn2 & table_mask) != table_opcd)
+ continue;
+
+ /* Check validity of operands. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; ++opindex)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ return opcode;
+ }
+
+ return NULL;
+}
+
+/* Find a match for INSN in the SPE2 opcode table. */
+
+static const struct powerpc_opcode *
+lookup_spe2 (uint64_t insn)
+{
+ const struct powerpc_opcode *opcode, *opcode_end;
+ unsigned op, xop, seg;
+
+ op = PPC_OP (insn);
+ if (op != 0x4)
+ {
+ /* This is not SPE2 insn.
+ * All SPE2 instructions have OP=4 and differs by XOP */
+ return NULL;
+ }
+ xop = SPE2_XOP (insn);
+ seg = SPE2_XOP_TO_SEG (xop);
+
+ /* Find the first match in the opcode table for this major opcode. */
+ opcode_end = spe2_opcodes + spe2_opcd_indices[seg + 1];
+ for (opcode = spe2_opcodes + spe2_opcd_indices[seg];
+ opcode < opcode_end;
+ ++opcode)
+ {
+ uint64_t table_opcd = opcode->opcode;
+ uint64_t table_mask = opcode->mask;
+ uint64_t insn2;
+ const unsigned char *opindex;
+ const struct powerpc_operand *operand;
+ int invalid;
+
+ insn2 = insn;
+ if ((insn2 & table_mask) != table_opcd)
+ continue;
+
+ /* Check validity of operands. */
+ invalid = 0;
+ for (opindex = opcode->operands; *opindex != 0; ++opindex)
+ {
+ operand = powerpc_operands + *opindex;
+ if (operand->extract)
+ (*operand->extract) (insn, (ppc_cpu_t)0, &invalid);
+ }
+ if (invalid)
+ continue;
+
+ return opcode;