code motion to remove opcode callback table from
translate_init.c.inc to translate.c in preparation to remove
the #include <translate_init.c.inc> from translate.c. Also created
destroy_ppc_opcodes and removed that logic from ppc_cpu_unrealize
Signed-off-by: Bruno Larsen (billionai) <bruno.larsen@eldorado.org.br>
---
target/ppc/internal.h | 8 +
target/ppc/translate.c | 394 ++++++++++++++++++++++++++++++++
target/ppc/translate_init.c.inc | 391 +------------------------------
3 files changed, 403 insertions(+), 390 deletions(-)
diff --git a/target/ppc/internal.h b/target/ppc/internal.h
index c401658e8d..184ba6d6b3 100644
--- a/target/ppc/internal.h
+++ b/target/ppc/internal.h
@@ -216,6 +216,14 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
+/* translate.c */
+
+/* #define PPC_DUMP_CPU */
+
+int ppc_fixup_cpu(PowerPCCPU *cpu);
+void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp);
+void destroy_ppc_opcodes(PowerPCCPU *cpu);
+
/* gdbstub.c */
void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
gchar *ppc_gdb_arch_name(CPUState *cs);
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 0984ce637b..b319d409c6 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -7825,6 +7825,400 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
#undef RFPL
}
+/*****************************************************************************/
+/* Opcode types */
+enum {
+ PPC_DIRECT = 0, /* Opcode routine */
+ PPC_INDIRECT = 1, /* Indirect opcode table */
+};
+
+#define PPC_OPCODE_MASK 0x3
+
+static inline int is_indirect_opcode(void *handler)
+{
+ return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
+}
+
+static inline opc_handler_t **ind_table(void *handler)
+{
+ return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
+}
+
+/* Instruction table creation */
+/* Opcodes tables creation */
+static void fill_new_table(opc_handler_t **table, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++) {
+ table[i] = &invalid_handler;
+ }
+}
+
+static int create_new_table(opc_handler_t **table, unsigned char idx)
+{
+ opc_handler_t **tmp;
+
+ tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
+ fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
+ table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
+
+ return 0;
+}
+
+static int insert_in_table(opc_handler_t **table, unsigned char idx,
+ opc_handler_t *handler)
+{
+ if (table[idx] != &invalid_handler) {
+ return -1;
+ }
+ table[idx] = handler;
+
+ return 0;
+}
+
+static int register_direct_insn(opc_handler_t **ppc_opcodes,
+ unsigned char idx, opc_handler_t *handler)
+{
+ if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
+ printf("*** ERROR: opcode %02x already assigned in main "
+ "opcode table\n", idx);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+ printf(" Registered handler '%s' - new handler '%s'\n",
+ ppc_opcodes[idx]->oname, handler->oname);
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+static int register_ind_in_table(opc_handler_t **table,
+ unsigned char idx1, unsigned char idx2,
+ opc_handler_t *handler)
+{
+ if (table[idx1] == &invalid_handler) {
+ if (create_new_table(table, idx1) < 0) {
+ printf("*** ERROR: unable to create indirect table "
+ "idx=%02x\n", idx1);
+ return -1;
+ }
+ } else {
+ if (!is_indirect_opcode(table[idx1])) {
+ printf("*** ERROR: idx %02x already assigned to a direct "
+ "opcode\n", idx1);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+ printf(" Registered handler '%s' - new handler '%s'\n",
+ ind_table(table[idx1])[idx2]->oname, handler->oname);
+#endif
+ return -1;
+ }
+ }
+ if (handler != NULL &&
+ insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
+ printf("*** ERROR: opcode %02x already assigned in "
+ "opcode table %02x\n", idx2, idx1);
+#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
+ printf(" Registered handler '%s' - new handler '%s'\n",
+ ind_table(table[idx1])[idx2]->oname, handler->oname);
+#endif
+ return -1;
+ }
+
+ return 0;
+}
+
+static int register_ind_insn(opc_handler_t **ppc_opcodes,
+ unsigned char idx1, unsigned char idx2,
+ opc_handler_t *handler)
+{
+ return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
+}
+
+static int register_dblind_insn(opc_handler_t **ppc_opcodes,
+ unsigned char idx1, unsigned char idx2,
+ unsigned char idx3, opc_handler_t *handler)
+{
+ if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
+ printf("*** ERROR: unable to join indirect table idx "
+ "[%02x-%02x]\n", idx1, idx2);
+ return -1;
+ }
+ if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
+ handler) < 0) {
+ printf("*** ERROR: unable to insert opcode "
+ "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
+ return -1;
+ }
+
+ return 0;
+}
+
+static int register_trplind_insn(opc_handler_t **ppc_opcodes,
+ unsigned char idx1, unsigned char idx2,
+ unsigned char idx3, unsigned char idx4,
+ opc_handler_t *handler)
+{
+ opc_handler_t **table;
+
+ if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
+ printf("*** ERROR: unable to join indirect table idx "
+ "[%02x-%02x]\n", idx1, idx2);
+ return -1;
+ }
+ table = ind_table(ppc_opcodes[idx1]);
+ if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
+ printf("*** ERROR: unable to join 2nd-level indirect table idx "
+ "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
+ return -1;
+ }
+ table = ind_table(table[idx2]);
+ if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
+ printf("*** ERROR: unable to insert opcode "
+ "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
+ return -1;
+ }
+ return 0;
+}
+static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
+{
+ if (insn->opc2 != 0xFF) {
+ if (insn->opc3 != 0xFF) {
+ if (insn->opc4 != 0xFF) {
+ if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
+ insn->opc3, insn->opc4,
+ &insn->handler) < 0) {
+ return -1;
+ }
+ } else {
+ if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
+ insn->opc3, &insn->handler) < 0) {
+ return -1;
+ }
+ }
+ } else {
+ if (register_ind_insn(ppc_opcodes, insn->opc1,
+ insn->opc2, &insn->handler) < 0) {
+ return -1;
+ }
+ }
+ } else {
+ if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int test_opcode_table(opc_handler_t **table, int len)
+{
+ int i, count, tmp;
+
+ for (i = 0, count = 0; i < len; i++) {
+ /* Consistency fixup */
+ if (table[i] == NULL) {
+ table[i] = &invalid_handler;
+ }
+ if (table[i] != &invalid_handler) {
+ if (is_indirect_opcode(table[i])) {
+ tmp = test_opcode_table(ind_table(table[i]),
+ PPC_CPU_INDIRECT_OPCODES_LEN);
+ if (tmp == 0) {
+ free(table[i]);
+ table[i] = &invalid_handler;
+ } else {
+ count++;
+ }
+ } else {
+ count++;
+ }
+ }
+ }
+
+ return count;
+}
+
+static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
+{
+ if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
+ printf("*** WARNING: no opcode defined !\n");
+ }
+}
+
+/*****************************************************************************/
+void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
+{
+ PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+ opcode_t *opc;
+
+ fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
+ for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
+ if (((opc->handler.type & pcc->insns_flags) != 0) ||
+ ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
+ if (register_insn(cpu->opcodes, opc) < 0) {
+ error_setg(errp, "ERROR initializing PowerPC instruction "
+ "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
+ opc->opc3);
+ return;
+ }
+ }
+ }
+ fix_opcode_tables(cpu->opcodes);
+ fflush(stdout);
+ fflush(stderr);
+}
+
+void destroy_ppc_opcodes(PowerPCCPU *cpu)
+{
+ opc_handler_t **table, **table_2;
+ int i, j, k;
+
+ for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
+ if (cpu->opcodes[i] == &invalid_handler) {
+ continue;
+ }
+ if (is_indirect_opcode(cpu->opcodes[i])) {
+ table = ind_table(cpu->opcodes[i]);
+ for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
+ if (table[j] == &invalid_handler) {
+ continue;
+ }
+ if (is_indirect_opcode(table[j])) {
+ table_2 = ind_table(table[j]);
+ for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
+ if (table_2[k] != &invalid_handler &&
+ is_indirect_opcode(table_2[k])) {
+ g_free((opc_handler_t *)((uintptr_t)table_2[k] &
+ ~PPC_INDIRECT));
+ }
+ }
+ g_free((opc_handler_t *)((uintptr_t)table[j] &
+ ~PPC_INDIRECT));
+ }
+ }
+ g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
+ ~PPC_INDIRECT));
+ }
+ }
+}
+
+#if defined(PPC_DUMP_CPU)
+static void dump_ppc_insns(CPUPPCState *env)
+{
+ opc_handler_t **table, *handler;
+ const char *p, *q;
+ uint8_t opc1, opc2, opc3, opc4;
+
+ printf("Instructions set:\n");
+ /* opc1 is 6 bits long */
+ for (opc1 = 0x00; opc1 < PPC_CPU_OPCODES_LEN; opc1++) {
+ table = env->opcodes;
+ handler = table[opc1];
+ if (is_indirect_opcode(handler)) {
+ /* opc2 is 5 bits long */
+ for (opc2 = 0; opc2 < PPC_CPU_INDIRECT_OPCODES_LEN; opc2++) {
+ table = env->opcodes;
+ handler = env->opcodes[opc1];
+ table = ind_table(handler);
+ handler = table[opc2];
+ if (is_indirect_opcode(handler)) {
+ table = ind_table(handler);
+ /* opc3 is 5 bits long */
+ for (opc3 = 0; opc3 < PPC_CPU_INDIRECT_OPCODES_LEN;
+ opc3++) {
+ handler = table[opc3];
+ if (is_indirect_opcode(handler)) {
+ table = ind_table(handler);
+ /* opc4 is 5 bits long */
+ for (opc4 = 0; opc4 < PPC_CPU_INDIRECT_OPCODES_LEN;
+ opc4++) {
+ handler = table[opc4];
+ if (handler->handler != &gen_invalid) {
+ printf("INSN: %02x %02x %02x %02x -- "
+ "(%02d %04d %02d) : %s\n",
+ opc1, opc2, opc3, opc4,
+ opc1, (opc3 << 5) | opc2, opc4,
+ handler->oname);
+ }
+ }
+ } else {
+ if (handler->handler != &gen_invalid) {
+ /* Special hack to properly dump SPE insns */
+ p = strchr(handler->oname, '_');
+ if (p == NULL) {
+ printf("INSN: %02x %02x %02x (%02d %04d) : "
+ "%s\n",
+ opc1, opc2, opc3, opc1,
+ (opc3 << 5) | opc2,
+ handler->oname);
+ } else {
+ q = "speundef";
+ if ((p - handler->oname) != strlen(q)
+ || (memcmp(handler->oname, q, strlen(q))
+ != 0)) {
+ /* First instruction */
+ printf("INSN: %02x %02x %02x"
+ "(%02d %04d) : %.*s\n",
+ opc1, opc2 << 1, opc3, opc1,
+ (opc3 << 6) | (opc2 << 1),
+ (int)(p - handler->oname),
+ handler->oname);
+ }
+ if (strcmp(p + 1, q) != 0) {
+ /* Second instruction */
+ printf("INSN: %02x %02x %02x "
+ "(%02d %04d) : %s\n", opc1,
+ (opc2 << 1) | 1, opc3, opc1,
+ (opc3 << 6) | (opc2 << 1) | 1,
+ p + 1);
+ }
+ }
+ }
+ }
+ }
+ } else {
+ if (handler->handler != &gen_invalid) {
+ printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
+ opc1, opc2, opc1, opc2, handler->oname);
+ }
+ }
+ }
+ } else {
+ if (handler->handler != &gen_invalid) {
+ printf("INSN: %02x -- -- (%02d ----) : %s\n",
+ opc1, opc1, handler->oname);
+ }
+ }
+ }
+}
+#endif
+int ppc_fixup_cpu(PowerPCCPU *cpu)
+{
+ CPUPPCState *env = &cpu->env;
+
+ /*
+ * TCG doesn't (yet) emulate some groups of instructions that are
+ * implemented on some otherwise supported CPUs (e.g. VSX and
+ * decimal floating point instructions on POWER7). We remove
+ * unsupported instruction groups from the cpu state's instruction
+ * masks and hope the guest can cope. For at least the pseries
+ * machine, the unavailability of these instructions can be
+ * advertised to the guest via the device tree.
+ */
+ if ((env->insns_flags & ~PPC_TCG_INSNS)
+ || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
+ warn_report("Disabling some instructions which are not "
+ "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
+ env->insns_flags & ~PPC_TCG_INSNS,
+ env->insns_flags2 & ~PPC_TCG_INSNS2);
+ }
+ env->insns_flags &= PPC_TCG_INSNS;
+ env->insns_flags2 &= PPC_TCG_INSNS2;
+ return 0;
+}
+
+
void ppc_cpu_dump_statistics(CPUState *cs, int flags)
{
#if defined(DO_PPC_STATISTICS)
diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index 80fef0b90d..6235eb7536 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -42,7 +42,6 @@
#include "fpu/softfloat.h"
#include "qapi/qapi-commands-machine-target.h"
-/* #define PPC_DUMP_CPU */
/* #define PPC_DEBUG_SPR */
/* #define PPC_DUMP_SPR_ACCESSES */
/* #define USE_APPLE_GDB */
@@ -9560,366 +9559,6 @@ static void dump_ppc_sprs(CPUPPCState *env)
}
#endif
-/*****************************************************************************/
-
-/* Opcode types */
-enum {
- PPC_DIRECT = 0, /* Opcode routine */
- PPC_INDIRECT = 1, /* Indirect opcode table */
-};
-
-#define PPC_OPCODE_MASK 0x3
-
-static inline int is_indirect_opcode(void *handler)
-{
- return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
-}
-
-static inline opc_handler_t **ind_table(void *handler)
-{
- return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
-}
-
-/* Instruction table creation */
-/* Opcodes tables creation */
-static void fill_new_table(opc_handler_t **table, int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- table[i] = &invalid_handler;
- }
-}
-
-static int create_new_table(opc_handler_t **table, unsigned char idx)
-{
- opc_handler_t **tmp;
-
- tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
- fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
- table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
-
- return 0;
-}
-
-static int insert_in_table(opc_handler_t **table, unsigned char idx,
- opc_handler_t *handler)
-{
- if (table[idx] != &invalid_handler) {
- return -1;
- }
- table[idx] = handler;
-
- return 0;
-}
-
-static int register_direct_insn(opc_handler_t **ppc_opcodes,
- unsigned char idx, opc_handler_t *handler)
-{
- if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
- printf("*** ERROR: opcode %02x already assigned in main "
- "opcode table\n", idx);
-#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
- printf(" Registered handler '%s' - new handler '%s'\n",
- ppc_opcodes[idx]->oname, handler->oname);
-#endif
- return -1;
- }
-
- return 0;
-}
-
-static int register_ind_in_table(opc_handler_t **table,
- unsigned char idx1, unsigned char idx2,
- opc_handler_t *handler)
-{
- if (table[idx1] == &invalid_handler) {
- if (create_new_table(table, idx1) < 0) {
- printf("*** ERROR: unable to create indirect table "
- "idx=%02x\n", idx1);
- return -1;
- }
- } else {
- if (!is_indirect_opcode(table[idx1])) {
- printf("*** ERROR: idx %02x already assigned to a direct "
- "opcode\n", idx1);
-#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
- printf(" Registered handler '%s' - new handler '%s'\n",
- ind_table(table[idx1])[idx2]->oname, handler->oname);
-#endif
- return -1;
- }
- }
- if (handler != NULL &&
- insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
- printf("*** ERROR: opcode %02x already assigned in "
- "opcode table %02x\n", idx2, idx1);
-#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
- printf(" Registered handler '%s' - new handler '%s'\n",
- ind_table(table[idx1])[idx2]->oname, handler->oname);
-#endif
- return -1;
- }
-
- return 0;
-}
-
-static int register_ind_insn(opc_handler_t **ppc_opcodes,
- unsigned char idx1, unsigned char idx2,
- opc_handler_t *handler)
-{
- return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
-}
-
-static int register_dblind_insn(opc_handler_t **ppc_opcodes,
- unsigned char idx1, unsigned char idx2,
- unsigned char idx3, opc_handler_t *handler)
-{
- if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
- printf("*** ERROR: unable to join indirect table idx "
- "[%02x-%02x]\n", idx1, idx2);
- return -1;
- }
- if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
- handler) < 0) {
- printf("*** ERROR: unable to insert opcode "
- "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
- return -1;
- }
-
- return 0;
-}
-
-static int register_trplind_insn(opc_handler_t **ppc_opcodes,
- unsigned char idx1, unsigned char idx2,
- unsigned char idx3, unsigned char idx4,
- opc_handler_t *handler)
-{
- opc_handler_t **table;
-
- if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
- printf("*** ERROR: unable to join indirect table idx "
- "[%02x-%02x]\n", idx1, idx2);
- return -1;
- }
- table = ind_table(ppc_opcodes[idx1]);
- if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
- printf("*** ERROR: unable to join 2nd-level indirect table idx "
- "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
- return -1;
- }
- table = ind_table(table[idx2]);
- if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
- printf("*** ERROR: unable to insert opcode "
- "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
- return -1;
- }
- return 0;
-}
-static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
-{
- if (insn->opc2 != 0xFF) {
- if (insn->opc3 != 0xFF) {
- if (insn->opc4 != 0xFF) {
- if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
- insn->opc3, insn->opc4,
- &insn->handler) < 0) {
- return -1;
- }
- } else {
- if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
- insn->opc3, &insn->handler) < 0) {
- return -1;
- }
- }
- } else {
- if (register_ind_insn(ppc_opcodes, insn->opc1,
- insn->opc2, &insn->handler) < 0) {
- return -1;
- }
- }
- } else {
- if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
- return -1;
- }
- }
-
- return 0;
-}
-
-static int test_opcode_table(opc_handler_t **table, int len)
-{
- int i, count, tmp;
-
- for (i = 0, count = 0; i < len; i++) {
- /* Consistency fixup */
- if (table[i] == NULL) {
- table[i] = &invalid_handler;
- }
- if (table[i] != &invalid_handler) {
- if (is_indirect_opcode(table[i])) {
- tmp = test_opcode_table(ind_table(table[i]),
- PPC_CPU_INDIRECT_OPCODES_LEN);
- if (tmp == 0) {
- free(table[i]);
- table[i] = &invalid_handler;
- } else {
- count++;
- }
- } else {
- count++;
- }
- }
- }
-
- return count;
-}
-
-static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
-{
- if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
- printf("*** WARNING: no opcode defined !\n");
- }
-}
-
-/*****************************************************************************/
-static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
-{
- PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- opcode_t *opc;
-
- fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
- for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
- if (((opc->handler.type & pcc->insns_flags) != 0) ||
- ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
- if (register_insn(cpu->opcodes, opc) < 0) {
- error_setg(errp, "ERROR initializing PowerPC instruction "
- "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
- opc->opc3);
- return;
- }
- }
- }
- fix_opcode_tables(cpu->opcodes);
- fflush(stdout);
- fflush(stderr);
-}
-
-#if defined(PPC_DUMP_CPU)
-static void dump_ppc_insns(CPUPPCState *env)
-{
- opc_handler_t **table, *handler;
- const char *p, *q;
- uint8_t opc1, opc2, opc3, opc4;
-
- printf("Instructions set:\n");
- /* opc1 is 6 bits long */
- for (opc1 = 0x00; opc1 < PPC_CPU_OPCODES_LEN; opc1++) {
- table = env->opcodes;
- handler = table[opc1];
- if (is_indirect_opcode(handler)) {
- /* opc2 is 5 bits long */
- for (opc2 = 0; opc2 < PPC_CPU_INDIRECT_OPCODES_LEN; opc2++) {
- table = env->opcodes;
- handler = env->opcodes[opc1];
- table = ind_table(handler);
- handler = table[opc2];
- if (is_indirect_opcode(handler)) {
- table = ind_table(handler);
- /* opc3 is 5 bits long */
- for (opc3 = 0; opc3 < PPC_CPU_INDIRECT_OPCODES_LEN;
- opc3++) {
- handler = table[opc3];
- if (is_indirect_opcode(handler)) {
- table = ind_table(handler);
- /* opc4 is 5 bits long */
- for (opc4 = 0; opc4 < PPC_CPU_INDIRECT_OPCODES_LEN;
- opc4++) {
- handler = table[opc4];
- if (handler->handler != &gen_invalid) {
- printf("INSN: %02x %02x %02x %02x -- "
- "(%02d %04d %02d) : %s\n",
- opc1, opc2, opc3, opc4,
- opc1, (opc3 << 5) | opc2, opc4,
- handler->oname);
- }
- }
- } else {
- if (handler->handler != &gen_invalid) {
- /* Special hack to properly dump SPE insns */
- p = strchr(handler->oname, '_');
- if (p == NULL) {
- printf("INSN: %02x %02x %02x (%02d %04d) : "
- "%s\n",
- opc1, opc2, opc3, opc1,
- (opc3 << 5) | opc2,
- handler->oname);
- } else {
- q = "speundef";
- if ((p - handler->oname) != strlen(q)
- || (memcmp(handler->oname, q, strlen(q))
- != 0)) {
- /* First instruction */
- printf("INSN: %02x %02x %02x"
- "(%02d %04d) : %.*s\n",
- opc1, opc2 << 1, opc3, opc1,
- (opc3 << 6) | (opc2 << 1),
- (int)(p - handler->oname),
- handler->oname);
- }
- if (strcmp(p + 1, q) != 0) {
- /* Second instruction */
- printf("INSN: %02x %02x %02x "
- "(%02d %04d) : %s\n", opc1,
- (opc2 << 1) | 1, opc3, opc1,
- (opc3 << 6) | (opc2 << 1) | 1,
- p + 1);
- }
- }
- }
- }
- }
- } else {
- if (handler->handler != &gen_invalid) {
- printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
- opc1, opc2, opc1, opc2, handler->oname);
- }
- }
- }
- } else {
- if (handler->handler != &gen_invalid) {
- printf("INSN: %02x -- -- (%02d ----) : %s\n",
- opc1, opc1, handler->oname);
- }
- }
- }
-}
-#endif
-static int ppc_fixup_cpu(PowerPCCPU *cpu)
-{
- CPUPPCState *env = &cpu->env;
-
- /*
- * TCG doesn't (yet) emulate some groups of instructions that are
- * implemented on some otherwise supported CPUs (e.g. VSX and
- * decimal floating point instructions on POWER7). We remove
- * unsupported instruction groups from the cpu state's instruction
- * masks and hope the guest can cope. For at least the pseries
- * machine, the unavailability of these instructions can be
- * advertised to the guest via the device tree.
- */
- if ((env->insns_flags & ~PPC_TCG_INSNS)
- || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
- warn_report("Disabling some instructions which are not "
- "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
- env->insns_flags & ~PPC_TCG_INSNS,
- env->insns_flags2 & ~PPC_TCG_INSNS2);
- }
- env->insns_flags &= PPC_TCG_INSNS;
- env->insns_flags2 &= PPC_TCG_INSNS2;
- return 0;
-}
-
static void ppc_cpu_realize(DeviceState *dev, Error **errp)
{
CPUState *cs = CPU(dev);
@@ -10131,40 +9770,12 @@ static void ppc_cpu_unrealize(DeviceState *dev)
{
PowerPCCPU *cpu = POWERPC_CPU(dev);
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
- opc_handler_t **table, **table_2;
- int i, j, k;
pcc->parent_unrealize(dev);
cpu_remove_sync(CPU(cpu));
- for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
- if (cpu->opcodes[i] == &invalid_handler) {
- continue;
- }
- if (is_indirect_opcode(cpu->opcodes[i])) {
- table = ind_table(cpu->opcodes[i]);
- for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
- if (table[j] == &invalid_handler) {
- continue;
- }
- if (is_indirect_opcode(table[j])) {
- table_2 = ind_table(table[j]);
- for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
- if (table_2[k] != &invalid_handler &&
- is_indirect_opcode(table_2[k])) {
- g_free((opc_handler_t *)((uintptr_t)table_2[k] &
- ~PPC_INDIRECT));
- }
- }
- g_free((opc_handler_t *)((uintptr_t)table[j] &
- ~PPC_INDIRECT));
- }
- }
- g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
- ~PPC_INDIRECT));
- }
- }
+ destroy_ppc_opcodes(cpu);
}
static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
--
2.17.1
On Thu, Apr 29, 2021 at 01:21:24PM -0300, Bruno Larsen (billionai) wrote:
65;6203;1c> code motion to remove opcode callback table from
> translate_init.c.inc to translate.c in preparation to remove
> the #include <translate_init.c.inc> from translate.c. Also created
> destroy_ppc_opcodes and removed that logic from ppc_cpu_unrealize
>
> Signed-off-by: Bruno Larsen (billionai)
> <bruno.larsen@eldorado.org.br>
Applied to ppc-for-6.1, thanks.
> ---
> target/ppc/internal.h | 8 +
> target/ppc/translate.c | 394 ++++++++++++++++++++++++++++++++
> target/ppc/translate_init.c.inc | 391 +------------------------------
> 3 files changed, 403 insertions(+), 390 deletions(-)
>
> diff --git a/target/ppc/internal.h b/target/ppc/internal.h
> index c401658e8d..184ba6d6b3 100644
> --- a/target/ppc/internal.h
> +++ b/target/ppc/internal.h
> @@ -216,6 +216,14 @@ void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
> MMUAccessType access_type,
> int mmu_idx, uintptr_t retaddr);
>
> +/* translate.c */
> +
> +/* #define PPC_DUMP_CPU */
> +
> +int ppc_fixup_cpu(PowerPCCPU *cpu);
> +void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp);
> +void destroy_ppc_opcodes(PowerPCCPU *cpu);
> +
> /* gdbstub.c */
> void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *ppc);
> gchar *ppc_gdb_arch_name(CPUState *cs);
> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
> index 0984ce637b..b319d409c6 100644
> --- a/target/ppc/translate.c
> +++ b/target/ppc/translate.c
> @@ -7825,6 +7825,400 @@ void ppc_cpu_dump_state(CPUState *cs, FILE *f, int flags)
> #undef RFPL
> }
>
> +/*****************************************************************************/
> +/* Opcode types */
> +enum {
> + PPC_DIRECT = 0, /* Opcode routine */
> + PPC_INDIRECT = 1, /* Indirect opcode table */
> +};
> +
> +#define PPC_OPCODE_MASK 0x3
> +
> +static inline int is_indirect_opcode(void *handler)
> +{
> + return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
> +}
> +
> +static inline opc_handler_t **ind_table(void *handler)
> +{
> + return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
> +}
> +
> +/* Instruction table creation */
> +/* Opcodes tables creation */
> +static void fill_new_table(opc_handler_t **table, int len)
> +{
> + int i;
> +
> + for (i = 0; i < len; i++) {
> + table[i] = &invalid_handler;
> + }
> +}
> +
> +static int create_new_table(opc_handler_t **table, unsigned char idx)
> +{
> + opc_handler_t **tmp;
> +
> + tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
> + fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
> + table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
> +
> + return 0;
> +}
> +
> +static int insert_in_table(opc_handler_t **table, unsigned char idx,
> + opc_handler_t *handler)
> +{
> + if (table[idx] != &invalid_handler) {
> + return -1;
> + }
> + table[idx] = handler;
> +
> + return 0;
> +}
> +
> +static int register_direct_insn(opc_handler_t **ppc_opcodes,
> + unsigned char idx, opc_handler_t *handler)
> +{
> + if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
> + printf("*** ERROR: opcode %02x already assigned in main "
> + "opcode table\n", idx);
> +#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> + printf(" Registered handler '%s' - new handler '%s'\n",
> + ppc_opcodes[idx]->oname, handler->oname);
> +#endif
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int register_ind_in_table(opc_handler_t **table,
> + unsigned char idx1, unsigned char idx2,
> + opc_handler_t *handler)
> +{
> + if (table[idx1] == &invalid_handler) {
> + if (create_new_table(table, idx1) < 0) {
> + printf("*** ERROR: unable to create indirect table "
> + "idx=%02x\n", idx1);
> + return -1;
> + }
> + } else {
> + if (!is_indirect_opcode(table[idx1])) {
> + printf("*** ERROR: idx %02x already assigned to a direct "
> + "opcode\n", idx1);
> +#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> + printf(" Registered handler '%s' - new handler '%s'\n",
> + ind_table(table[idx1])[idx2]->oname, handler->oname);
> +#endif
> + return -1;
> + }
> + }
> + if (handler != NULL &&
> + insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
> + printf("*** ERROR: opcode %02x already assigned in "
> + "opcode table %02x\n", idx2, idx1);
> +#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> + printf(" Registered handler '%s' - new handler '%s'\n",
> + ind_table(table[idx1])[idx2]->oname, handler->oname);
> +#endif
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int register_ind_insn(opc_handler_t **ppc_opcodes,
> + unsigned char idx1, unsigned char idx2,
> + opc_handler_t *handler)
> +{
> + return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
> +}
> +
> +static int register_dblind_insn(opc_handler_t **ppc_opcodes,
> + unsigned char idx1, unsigned char idx2,
> + unsigned char idx3, opc_handler_t *handler)
> +{
> + if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
> + printf("*** ERROR: unable to join indirect table idx "
> + "[%02x-%02x]\n", idx1, idx2);
> + return -1;
> + }
> + if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
> + handler) < 0) {
> + printf("*** ERROR: unable to insert opcode "
> + "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
> + return -1;
> + }
> +
> + return 0;
> +}
> +
> +static int register_trplind_insn(opc_handler_t **ppc_opcodes,
> + unsigned char idx1, unsigned char idx2,
> + unsigned char idx3, unsigned char idx4,
> + opc_handler_t *handler)
> +{
> + opc_handler_t **table;
> +
> + if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
> + printf("*** ERROR: unable to join indirect table idx "
> + "[%02x-%02x]\n", idx1, idx2);
> + return -1;
> + }
> + table = ind_table(ppc_opcodes[idx1]);
> + if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
> + printf("*** ERROR: unable to join 2nd-level indirect table idx "
> + "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
> + return -1;
> + }
> + table = ind_table(table[idx2]);
> + if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
> + printf("*** ERROR: unable to insert opcode "
> + "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
> + return -1;
> + }
> + return 0;
> +}
> +static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
> +{
> + if (insn->opc2 != 0xFF) {
> + if (insn->opc3 != 0xFF) {
> + if (insn->opc4 != 0xFF) {
> + if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
> + insn->opc3, insn->opc4,
> + &insn->handler) < 0) {
> + return -1;
> + }
> + } else {
> + if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
> + insn->opc3, &insn->handler) < 0) {
> + return -1;
> + }
> + }
> + } else {
> + if (register_ind_insn(ppc_opcodes, insn->opc1,
> + insn->opc2, &insn->handler) < 0) {
> + return -1;
> + }
> + }
> + } else {
> + if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
> + return -1;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static int test_opcode_table(opc_handler_t **table, int len)
> +{
> + int i, count, tmp;
> +
> + for (i = 0, count = 0; i < len; i++) {
> + /* Consistency fixup */
> + if (table[i] == NULL) {
> + table[i] = &invalid_handler;
> + }
> + if (table[i] != &invalid_handler) {
> + if (is_indirect_opcode(table[i])) {
> + tmp = test_opcode_table(ind_table(table[i]),
> + PPC_CPU_INDIRECT_OPCODES_LEN);
> + if (tmp == 0) {
> + free(table[i]);
> + table[i] = &invalid_handler;
> + } else {
> + count++;
> + }
> + } else {
> + count++;
> + }
> + }
> + }
> +
> + return count;
> +}
> +
> +static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
> +{
> + if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
> + printf("*** WARNING: no opcode defined !\n");
> + }
> +}
> +
> +/*****************************************************************************/
> +void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
> +{
> + PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> + opcode_t *opc;
> +
> + fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
> + for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
> + if (((opc->handler.type & pcc->insns_flags) != 0) ||
> + ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
> + if (register_insn(cpu->opcodes, opc) < 0) {
> + error_setg(errp, "ERROR initializing PowerPC instruction "
> + "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
> + opc->opc3);
> + return;
> + }
> + }
> + }
> + fix_opcode_tables(cpu->opcodes);
> + fflush(stdout);
> + fflush(stderr);
> +}
> +
> +void destroy_ppc_opcodes(PowerPCCPU *cpu)
> +{
> + opc_handler_t **table, **table_2;
> + int i, j, k;
> +
> + for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
> + if (cpu->opcodes[i] == &invalid_handler) {
> + continue;
> + }
> + if (is_indirect_opcode(cpu->opcodes[i])) {
> + table = ind_table(cpu->opcodes[i]);
> + for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
> + if (table[j] == &invalid_handler) {
> + continue;
> + }
> + if (is_indirect_opcode(table[j])) {
> + table_2 = ind_table(table[j]);
> + for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
> + if (table_2[k] != &invalid_handler &&
> + is_indirect_opcode(table_2[k])) {
> + g_free((opc_handler_t *)((uintptr_t)table_2[k] &
> + ~PPC_INDIRECT));
> + }
> + }
> + g_free((opc_handler_t *)((uintptr_t)table[j] &
> + ~PPC_INDIRECT));
> + }
> + }
> + g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
> + ~PPC_INDIRECT));
> + }
> + }
> +}
> +
> +#if defined(PPC_DUMP_CPU)
> +static void dump_ppc_insns(CPUPPCState *env)
> +{
> + opc_handler_t **table, *handler;
> + const char *p, *q;
> + uint8_t opc1, opc2, opc3, opc4;
> +
> + printf("Instructions set:\n");
> + /* opc1 is 6 bits long */
> + for (opc1 = 0x00; opc1 < PPC_CPU_OPCODES_LEN; opc1++) {
> + table = env->opcodes;
> + handler = table[opc1];
> + if (is_indirect_opcode(handler)) {
> + /* opc2 is 5 bits long */
> + for (opc2 = 0; opc2 < PPC_CPU_INDIRECT_OPCODES_LEN; opc2++) {
> + table = env->opcodes;
> + handler = env->opcodes[opc1];
> + table = ind_table(handler);
> + handler = table[opc2];
> + if (is_indirect_opcode(handler)) {
> + table = ind_table(handler);
> + /* opc3 is 5 bits long */
> + for (opc3 = 0; opc3 < PPC_CPU_INDIRECT_OPCODES_LEN;
> + opc3++) {
> + handler = table[opc3];
> + if (is_indirect_opcode(handler)) {
> + table = ind_table(handler);
> + /* opc4 is 5 bits long */
> + for (opc4 = 0; opc4 < PPC_CPU_INDIRECT_OPCODES_LEN;
> + opc4++) {
> + handler = table[opc4];
> + if (handler->handler != &gen_invalid) {
> + printf("INSN: %02x %02x %02x %02x -- "
> + "(%02d %04d %02d) : %s\n",
> + opc1, opc2, opc3, opc4,
> + opc1, (opc3 << 5) | opc2, opc4,
> + handler->oname);
> + }
> + }
> + } else {
> + if (handler->handler != &gen_invalid) {
> + /* Special hack to properly dump SPE insns */
> + p = strchr(handler->oname, '_');
> + if (p == NULL) {
> + printf("INSN: %02x %02x %02x (%02d %04d) : "
> + "%s\n",
> + opc1, opc2, opc3, opc1,
> + (opc3 << 5) | opc2,
> + handler->oname);
> + } else {
> + q = "speundef";
> + if ((p - handler->oname) != strlen(q)
> + || (memcmp(handler->oname, q, strlen(q))
> + != 0)) {
> + /* First instruction */
> + printf("INSN: %02x %02x %02x"
> + "(%02d %04d) : %.*s\n",
> + opc1, opc2 << 1, opc3, opc1,
> + (opc3 << 6) | (opc2 << 1),
> + (int)(p - handler->oname),
> + handler->oname);
> + }
> + if (strcmp(p + 1, q) != 0) {
> + /* Second instruction */
> + printf("INSN: %02x %02x %02x "
> + "(%02d %04d) : %s\n", opc1,
> + (opc2 << 1) | 1, opc3, opc1,
> + (opc3 << 6) | (opc2 << 1) | 1,
> + p + 1);
> + }
> + }
> + }
> + }
> + }
> + } else {
> + if (handler->handler != &gen_invalid) {
> + printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
> + opc1, opc2, opc1, opc2, handler->oname);
> + }
> + }
> + }
> + } else {
> + if (handler->handler != &gen_invalid) {
> + printf("INSN: %02x -- -- (%02d ----) : %s\n",
> + opc1, opc1, handler->oname);
> + }
> + }
> + }
> +}
> +#endif
> +int ppc_fixup_cpu(PowerPCCPU *cpu)
> +{
> + CPUPPCState *env = &cpu->env;
> +
> + /*
> + * TCG doesn't (yet) emulate some groups of instructions that are
> + * implemented on some otherwise supported CPUs (e.g. VSX and
> + * decimal floating point instructions on POWER7). We remove
> + * unsupported instruction groups from the cpu state's instruction
> + * masks and hope the guest can cope. For at least the pseries
> + * machine, the unavailability of these instructions can be
> + * advertised to the guest via the device tree.
> + */
> + if ((env->insns_flags & ~PPC_TCG_INSNS)
> + || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
> + warn_report("Disabling some instructions which are not "
> + "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
> + env->insns_flags & ~PPC_TCG_INSNS,
> + env->insns_flags2 & ~PPC_TCG_INSNS2);
> + }
> + env->insns_flags &= PPC_TCG_INSNS;
> + env->insns_flags2 &= PPC_TCG_INSNS2;
> + return 0;
> +}
> +
> +
> void ppc_cpu_dump_statistics(CPUState *cs, int flags)
> {
> #if defined(DO_PPC_STATISTICS)
> diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
> index 80fef0b90d..6235eb7536 100644
> --- a/target/ppc/translate_init.c.inc
> +++ b/target/ppc/translate_init.c.inc
> @@ -42,7 +42,6 @@
> #include "fpu/softfloat.h"
> #include "qapi/qapi-commands-machine-target.h"
>
> -/* #define PPC_DUMP_CPU */
> /* #define PPC_DEBUG_SPR */
> /* #define PPC_DUMP_SPR_ACCESSES */
> /* #define USE_APPLE_GDB */
> @@ -9560,366 +9559,6 @@ static void dump_ppc_sprs(CPUPPCState *env)
> }
> #endif
>
> -/*****************************************************************************/
> -
> -/* Opcode types */
> -enum {
> - PPC_DIRECT = 0, /* Opcode routine */
> - PPC_INDIRECT = 1, /* Indirect opcode table */
> -};
> -
> -#define PPC_OPCODE_MASK 0x3
> -
> -static inline int is_indirect_opcode(void *handler)
> -{
> - return ((uintptr_t)handler & PPC_OPCODE_MASK) == PPC_INDIRECT;
> -}
> -
> -static inline opc_handler_t **ind_table(void *handler)
> -{
> - return (opc_handler_t **)((uintptr_t)handler & ~PPC_OPCODE_MASK);
> -}
> -
> -/* Instruction table creation */
> -/* Opcodes tables creation */
> -static void fill_new_table(opc_handler_t **table, int len)
> -{
> - int i;
> -
> - for (i = 0; i < len; i++) {
> - table[i] = &invalid_handler;
> - }
> -}
> -
> -static int create_new_table(opc_handler_t **table, unsigned char idx)
> -{
> - opc_handler_t **tmp;
> -
> - tmp = g_new(opc_handler_t *, PPC_CPU_INDIRECT_OPCODES_LEN);
> - fill_new_table(tmp, PPC_CPU_INDIRECT_OPCODES_LEN);
> - table[idx] = (opc_handler_t *)((uintptr_t)tmp | PPC_INDIRECT);
> -
> - return 0;
> -}
> -
> -static int insert_in_table(opc_handler_t **table, unsigned char idx,
> - opc_handler_t *handler)
> -{
> - if (table[idx] != &invalid_handler) {
> - return -1;
> - }
> - table[idx] = handler;
> -
> - return 0;
> -}
> -
> -static int register_direct_insn(opc_handler_t **ppc_opcodes,
> - unsigned char idx, opc_handler_t *handler)
> -{
> - if (insert_in_table(ppc_opcodes, idx, handler) < 0) {
> - printf("*** ERROR: opcode %02x already assigned in main "
> - "opcode table\n", idx);
> -#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> - printf(" Registered handler '%s' - new handler '%s'\n",
> - ppc_opcodes[idx]->oname, handler->oname);
> -#endif
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> -static int register_ind_in_table(opc_handler_t **table,
> - unsigned char idx1, unsigned char idx2,
> - opc_handler_t *handler)
> -{
> - if (table[idx1] == &invalid_handler) {
> - if (create_new_table(table, idx1) < 0) {
> - printf("*** ERROR: unable to create indirect table "
> - "idx=%02x\n", idx1);
> - return -1;
> - }
> - } else {
> - if (!is_indirect_opcode(table[idx1])) {
> - printf("*** ERROR: idx %02x already assigned to a direct "
> - "opcode\n", idx1);
> -#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> - printf(" Registered handler '%s' - new handler '%s'\n",
> - ind_table(table[idx1])[idx2]->oname, handler->oname);
> -#endif
> - return -1;
> - }
> - }
> - if (handler != NULL &&
> - insert_in_table(ind_table(table[idx1]), idx2, handler) < 0) {
> - printf("*** ERROR: opcode %02x already assigned in "
> - "opcode table %02x\n", idx2, idx1);
> -#if defined(DO_PPC_STATISTICS) || defined(PPC_DUMP_CPU)
> - printf(" Registered handler '%s' - new handler '%s'\n",
> - ind_table(table[idx1])[idx2]->oname, handler->oname);
> -#endif
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> -static int register_ind_insn(opc_handler_t **ppc_opcodes,
> - unsigned char idx1, unsigned char idx2,
> - opc_handler_t *handler)
> -{
> - return register_ind_in_table(ppc_opcodes, idx1, idx2, handler);
> -}
> -
> -static int register_dblind_insn(opc_handler_t **ppc_opcodes,
> - unsigned char idx1, unsigned char idx2,
> - unsigned char idx3, opc_handler_t *handler)
> -{
> - if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
> - printf("*** ERROR: unable to join indirect table idx "
> - "[%02x-%02x]\n", idx1, idx2);
> - return -1;
> - }
> - if (register_ind_in_table(ind_table(ppc_opcodes[idx1]), idx2, idx3,
> - handler) < 0) {
> - printf("*** ERROR: unable to insert opcode "
> - "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
> - return -1;
> - }
> -
> - return 0;
> -}
> -
> -static int register_trplind_insn(opc_handler_t **ppc_opcodes,
> - unsigned char idx1, unsigned char idx2,
> - unsigned char idx3, unsigned char idx4,
> - opc_handler_t *handler)
> -{
> - opc_handler_t **table;
> -
> - if (register_ind_in_table(ppc_opcodes, idx1, idx2, NULL) < 0) {
> - printf("*** ERROR: unable to join indirect table idx "
> - "[%02x-%02x]\n", idx1, idx2);
> - return -1;
> - }
> - table = ind_table(ppc_opcodes[idx1]);
> - if (register_ind_in_table(table, idx2, idx3, NULL) < 0) {
> - printf("*** ERROR: unable to join 2nd-level indirect table idx "
> - "[%02x-%02x-%02x]\n", idx1, idx2, idx3);
> - return -1;
> - }
> - table = ind_table(table[idx2]);
> - if (register_ind_in_table(table, idx3, idx4, handler) < 0) {
> - printf("*** ERROR: unable to insert opcode "
> - "[%02x-%02x-%02x-%02x]\n", idx1, idx2, idx3, idx4);
> - return -1;
> - }
> - return 0;
> -}
> -static int register_insn(opc_handler_t **ppc_opcodes, opcode_t *insn)
> -{
> - if (insn->opc2 != 0xFF) {
> - if (insn->opc3 != 0xFF) {
> - if (insn->opc4 != 0xFF) {
> - if (register_trplind_insn(ppc_opcodes, insn->opc1, insn->opc2,
> - insn->opc3, insn->opc4,
> - &insn->handler) < 0) {
> - return -1;
> - }
> - } else {
> - if (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
> - insn->opc3, &insn->handler) < 0) {
> - return -1;
> - }
> - }
> - } else {
> - if (register_ind_insn(ppc_opcodes, insn->opc1,
> - insn->opc2, &insn->handler) < 0) {
> - return -1;
> - }
> - }
> - } else {
> - if (register_direct_insn(ppc_opcodes, insn->opc1, &insn->handler) < 0) {
> - return -1;
> - }
> - }
> -
> - return 0;
> -}
> -
> -static int test_opcode_table(opc_handler_t **table, int len)
> -{
> - int i, count, tmp;
> -
> - for (i = 0, count = 0; i < len; i++) {
> - /* Consistency fixup */
> - if (table[i] == NULL) {
> - table[i] = &invalid_handler;
> - }
> - if (table[i] != &invalid_handler) {
> - if (is_indirect_opcode(table[i])) {
> - tmp = test_opcode_table(ind_table(table[i]),
> - PPC_CPU_INDIRECT_OPCODES_LEN);
> - if (tmp == 0) {
> - free(table[i]);
> - table[i] = &invalid_handler;
> - } else {
> - count++;
> - }
> - } else {
> - count++;
> - }
> - }
> - }
> -
> - return count;
> -}
> -
> -static void fix_opcode_tables(opc_handler_t **ppc_opcodes)
> -{
> - if (test_opcode_table(ppc_opcodes, PPC_CPU_OPCODES_LEN) == 0) {
> - printf("*** WARNING: no opcode defined !\n");
> - }
> -}
> -
> -/*****************************************************************************/
> -static void create_ppc_opcodes(PowerPCCPU *cpu, Error **errp)
> -{
> - PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> - opcode_t *opc;
> -
> - fill_new_table(cpu->opcodes, PPC_CPU_OPCODES_LEN);
> - for (opc = opcodes; opc < &opcodes[ARRAY_SIZE(opcodes)]; opc++) {
> - if (((opc->handler.type & pcc->insns_flags) != 0) ||
> - ((opc->handler.type2 & pcc->insns_flags2) != 0)) {
> - if (register_insn(cpu->opcodes, opc) < 0) {
> - error_setg(errp, "ERROR initializing PowerPC instruction "
> - "0x%02x 0x%02x 0x%02x", opc->opc1, opc->opc2,
> - opc->opc3);
> - return;
> - }
> - }
> - }
> - fix_opcode_tables(cpu->opcodes);
> - fflush(stdout);
> - fflush(stderr);
> -}
> -
> -#if defined(PPC_DUMP_CPU)
> -static void dump_ppc_insns(CPUPPCState *env)
> -{
> - opc_handler_t **table, *handler;
> - const char *p, *q;
> - uint8_t opc1, opc2, opc3, opc4;
> -
> - printf("Instructions set:\n");
> - /* opc1 is 6 bits long */
> - for (opc1 = 0x00; opc1 < PPC_CPU_OPCODES_LEN; opc1++) {
> - table = env->opcodes;
> - handler = table[opc1];
> - if (is_indirect_opcode(handler)) {
> - /* opc2 is 5 bits long */
> - for (opc2 = 0; opc2 < PPC_CPU_INDIRECT_OPCODES_LEN; opc2++) {
> - table = env->opcodes;
> - handler = env->opcodes[opc1];
> - table = ind_table(handler);
> - handler = table[opc2];
> - if (is_indirect_opcode(handler)) {
> - table = ind_table(handler);
> - /* opc3 is 5 bits long */
> - for (opc3 = 0; opc3 < PPC_CPU_INDIRECT_OPCODES_LEN;
> - opc3++) {
> - handler = table[opc3];
> - if (is_indirect_opcode(handler)) {
> - table = ind_table(handler);
> - /* opc4 is 5 bits long */
> - for (opc4 = 0; opc4 < PPC_CPU_INDIRECT_OPCODES_LEN;
> - opc4++) {
> - handler = table[opc4];
> - if (handler->handler != &gen_invalid) {
> - printf("INSN: %02x %02x %02x %02x -- "
> - "(%02d %04d %02d) : %s\n",
> - opc1, opc2, opc3, opc4,
> - opc1, (opc3 << 5) | opc2, opc4,
> - handler->oname);
> - }
> - }
> - } else {
> - if (handler->handler != &gen_invalid) {
> - /* Special hack to properly dump SPE insns */
> - p = strchr(handler->oname, '_');
> - if (p == NULL) {
> - printf("INSN: %02x %02x %02x (%02d %04d) : "
> - "%s\n",
> - opc1, opc2, opc3, opc1,
> - (opc3 << 5) | opc2,
> - handler->oname);
> - } else {
> - q = "speundef";
> - if ((p - handler->oname) != strlen(q)
> - || (memcmp(handler->oname, q, strlen(q))
> - != 0)) {
> - /* First instruction */
> - printf("INSN: %02x %02x %02x"
> - "(%02d %04d) : %.*s\n",
> - opc1, opc2 << 1, opc3, opc1,
> - (opc3 << 6) | (opc2 << 1),
> - (int)(p - handler->oname),
> - handler->oname);
> - }
> - if (strcmp(p + 1, q) != 0) {
> - /* Second instruction */
> - printf("INSN: %02x %02x %02x "
> - "(%02d %04d) : %s\n", opc1,
> - (opc2 << 1) | 1, opc3, opc1,
> - (opc3 << 6) | (opc2 << 1) | 1,
> - p + 1);
> - }
> - }
> - }
> - }
> - }
> - } else {
> - if (handler->handler != &gen_invalid) {
> - printf("INSN: %02x %02x -- (%02d %04d) : %s\n",
> - opc1, opc2, opc1, opc2, handler->oname);
> - }
> - }
> - }
> - } else {
> - if (handler->handler != &gen_invalid) {
> - printf("INSN: %02x -- -- (%02d ----) : %s\n",
> - opc1, opc1, handler->oname);
> - }
> - }
> - }
> -}
> -#endif
> -static int ppc_fixup_cpu(PowerPCCPU *cpu)
> -{
> - CPUPPCState *env = &cpu->env;
> -
> - /*
> - * TCG doesn't (yet) emulate some groups of instructions that are
> - * implemented on some otherwise supported CPUs (e.g. VSX and
> - * decimal floating point instructions on POWER7). We remove
> - * unsupported instruction groups from the cpu state's instruction
> - * masks and hope the guest can cope. For at least the pseries
> - * machine, the unavailability of these instructions can be
> - * advertised to the guest via the device tree.
> - */
> - if ((env->insns_flags & ~PPC_TCG_INSNS)
> - || (env->insns_flags2 & ~PPC_TCG_INSNS2)) {
> - warn_report("Disabling some instructions which are not "
> - "emulated by TCG (0x%" PRIx64 ", 0x%" PRIx64 ")",
> - env->insns_flags & ~PPC_TCG_INSNS,
> - env->insns_flags2 & ~PPC_TCG_INSNS2);
> - }
> - env->insns_flags &= PPC_TCG_INSNS;
> - env->insns_flags2 &= PPC_TCG_INSNS2;
> - return 0;
> -}
> -
> static void ppc_cpu_realize(DeviceState *dev, Error **errp)
> {
> CPUState *cs = CPU(dev);
> @@ -10131,40 +9770,12 @@ static void ppc_cpu_unrealize(DeviceState *dev)
> {
> PowerPCCPU *cpu = POWERPC_CPU(dev);
> PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
> - opc_handler_t **table, **table_2;
> - int i, j, k;
>
> pcc->parent_unrealize(dev);
>
> cpu_remove_sync(CPU(cpu));
>
> - for (i = 0; i < PPC_CPU_OPCODES_LEN; i++) {
> - if (cpu->opcodes[i] == &invalid_handler) {
> - continue;
> - }
> - if (is_indirect_opcode(cpu->opcodes[i])) {
> - table = ind_table(cpu->opcodes[i]);
> - for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
> - if (table[j] == &invalid_handler) {
> - continue;
> - }
> - if (is_indirect_opcode(table[j])) {
> - table_2 = ind_table(table[j]);
> - for (k = 0; k < PPC_CPU_INDIRECT_OPCODES_LEN; k++) {
> - if (table_2[k] != &invalid_handler &&
> - is_indirect_opcode(table_2[k])) {
> - g_free((opc_handler_t *)((uintptr_t)table_2[k] &
> - ~PPC_INDIRECT));
> - }
> - }
> - g_free((opc_handler_t *)((uintptr_t)table[j] &
> - ~PPC_INDIRECT));
> - }
> - }
> - g_free((opc_handler_t *)((uintptr_t)cpu->opcodes[i] &
> - ~PPC_INDIRECT));
> - }
> - }
> + destroy_ppc_opcodes(cpu);
> }
>
> static gint ppc_cpu_compare_class_pvr(gconstpointer a, gconstpointer b)
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
On 4/29/21 9:21 AM, Bruno Larsen (billionai) wrote: > code motion to remove opcode callback table from > translate_init.c.inc to translate.c in preparation to remove > the #include <translate_init.c.inc> from translate.c. Also created > destroy_ppc_opcodes and removed that logic from ppc_cpu_unrealize > > Signed-off-by: Bruno Larsen (billionai)<bruno.larsen@eldorado.org.br> > --- > target/ppc/internal.h | 8 + > target/ppc/translate.c | 394 ++++++++++++++++++++++++++++++++ > target/ppc/translate_init.c.inc | 391 +------------------------------ > 3 files changed, 403 insertions(+), 390 deletions(-) Reviewed-by: Richard Henderson <richard.henderson@linaro.org> r~
© 2016 - 2026 Red Hat, Inc.