+struct dis_private
+{
+ /* Stash the result of parsing disassembler_options here. */
+ ppc_cpu_t dialect;
+};
+
+#define POWERPC_DIALECT(INFO) \
+ (((struct dis_private *) ((INFO)->private_data))->dialect)
+
+/* Determine which set of machines to disassemble for. PPC403/601 or
+ BookE. For convenience, also disassemble instructions supported
+ by the AltiVec vector unit. */
+
+static int
+powerpc_init_dialect (struct disassemble_info *info)
+{
+ ppc_cpu_t dialect = PPC_OPCODE_PPC;
+ struct dis_private *priv = calloc (sizeof (*priv), 1);
+
+ if (priv == NULL)
+ return FALSE;
+
+ if (BFD_DEFAULT_TARGET_SIZE == 64)
+ dialect |= PPC_OPCODE_64;
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "ppcps") != NULL)
+ dialect |= PPC_OPCODE_PPCPS;
+ else if (info->disassembler_options
+ && strstr (info->disassembler_options, "booke") != NULL)
+ dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_BOOKE64;
+ else if ((info->mach == bfd_mach_ppc_e500mc)
+ || (info->disassembler_options
+ && strstr (info->disassembler_options, "e500mc") != NULL))
+ dialect |= (PPC_OPCODE_BOOKE | PPC_OPCODE_ISEL
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
+ else if ((info->mach == bfd_mach_ppc_e500)
+ || (info->disassembler_options
+ && strstr (info->disassembler_options, "e500") != NULL))
+ dialect |= (PPC_OPCODE_BOOKE
+ | PPC_OPCODE_SPE | PPC_OPCODE_ISEL
+ | PPC_OPCODE_EFS | PPC_OPCODE_BRLOCK
+ | PPC_OPCODE_PMR | PPC_OPCODE_CACHELCK
+ | PPC_OPCODE_RFMCI | PPC_OPCODE_E500MC);
+ else if (info->disassembler_options
+ && strstr (info->disassembler_options, "efs") != NULL)
+ dialect |= PPC_OPCODE_EFS;
+ else if (info->disassembler_options
+ && strstr (info->disassembler_options, "e300") != NULL)
+ dialect |= PPC_OPCODE_E300 | PPC_OPCODE_CLASSIC | PPC_OPCODE_COMMON;
+ else if (info->disassembler_options
+ && (strstr (info->disassembler_options, "440") != NULL
+ || strstr (info->disassembler_options, "464") != NULL))
+ dialect |= PPC_OPCODE_BOOKE | PPC_OPCODE_32
+ | PPC_OPCODE_440 | PPC_OPCODE_ISEL | PPC_OPCODE_RFMCI;
+ else
+ dialect |= (PPC_OPCODE_403 | PPC_OPCODE_601 | PPC_OPCODE_CLASSIC
+ | PPC_OPCODE_COMMON | PPC_OPCODE_ALTIVEC);
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "power4") != NULL)
+ dialect |= PPC_OPCODE_POWER4;
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "power5") != NULL)
+ dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5;
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "cell") != NULL)
+ dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_CELL | PPC_OPCODE_ALTIVEC;
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "power6") != NULL)
+ dialect |= PPC_OPCODE_POWER4 | PPC_OPCODE_POWER5 | PPC_OPCODE_POWER6 | PPC_OPCODE_ALTIVEC;
+
+ if (info->disassembler_options
+ && strstr (info->disassembler_options, "any") != NULL)
+ dialect |= PPC_OPCODE_ANY;
+
+ if (info->disassembler_options)
+ {
+ if (strstr (info->disassembler_options, "32") != NULL)
+ dialect &= ~PPC_OPCODE_64;
+ else if (strstr (info->disassembler_options, "64") != NULL)
+ dialect |= PPC_OPCODE_64;
+ }
+
+ info->private_data = priv;
+ POWERPC_DIALECT(info) = dialect;
+
+ return TRUE;
+}