From: David Gibson <david@gibson.dropbear.id.au>
To: "Bruno Larsen (billionai)" <bruno.larsen@eldorado.org.br>
Cc: farosas@linux.ibm.com, qemu-devel@nongnu.org,
lucas.araujo@eldorado.org.br, fernando.valle@eldorado.org.br,
qemu-ppc@nongnu.org, matheus.ferst@eldorado.org.br,
luis.pires@eldorado.org.br
Subject: Re: [PATCH v2 1/7] target/ppc: move opcode table logic to translate.c
Date: Fri, 30 Apr 2021 14:18:22 +1000 [thread overview]
Message-ID: <YIuFDrA8H02bGEuk@yekko> (raw)
In-Reply-To: <20210429162130.2412-2-bruno.larsen@eldorado.org.br>
[-- Attachment #1: Type: text/plain, Size: 35094 bytes --]
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
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
next prev parent reply other threads:[~2021-04-30 7:31 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-29 16:21 [PATCH v2 0/7] target/ppc: untangle cpu init from translation Bruno Larsen (billionai)
2021-04-29 16:21 ` [PATCH v2 1/7] target/ppc: move opcode table logic to translate.c Bruno Larsen (billionai)
2021-04-30 3:13 ` Richard Henderson
2021-04-30 4:18 ` David Gibson [this message]
2021-04-29 16:21 ` [PATCH v2 2/7] target/ppc: Created !TCG SPR registration macro Bruno Larsen (billionai)
2021-04-29 20:02 ` Fabiano Rosas
2021-04-29 16:21 ` [PATCH v2 3/7] target/ppc: Isolated SPR read/write callbacks Bruno Larsen (billionai)
2021-04-29 20:42 ` Fabiano Rosas
2021-04-30 3:33 ` Richard Henderson
2021-04-30 4:21 ` David Gibson
2021-04-30 13:02 ` Bruno Piazera Larsen
2021-05-03 3:54 ` David Gibson
2021-04-29 16:21 ` [PATCH v2 4/7] target/ppc: turned SPR R/W callbacks not static Bruno Larsen (billionai)
2021-04-29 20:52 ` Fabiano Rosas
2021-04-30 3:40 ` Richard Henderson
2021-04-30 17:26 ` Bruno Piazera Larsen
2021-04-30 4:34 ` Richard Henderson
2021-04-29 16:21 ` [PATCH v2 5/7] target/ppc: removed VSCR from SPR registration Bruno Larsen (billionai)
2021-04-29 16:21 ` [PATCH v2 6/7] target/ttc: renamed SPR registration functions Bruno Larsen (billionai)
2021-04-30 3:52 ` Richard Henderson
2021-04-29 16:21 ` [PATCH v2 7/7] target/ppc: isolated cpu init from translation logic Bruno Larsen (billionai)
2021-04-29 21:23 ` Fabiano Rosas
2021-04-30 17:12 ` Bruno Piazera Larsen
2021-04-30 17:42 ` Richard Henderson
2021-04-30 4:25 ` Richard Henderson
2021-04-30 14:35 ` Bruno Piazera Larsen
2021-04-30 3:12 ` [PATCH v2 0/7] target/ppc: untangle cpu init from translation Richard Henderson
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YIuFDrA8H02bGEuk@yekko \
--to=david@gibson.dropbear.id.au \
--cc=bruno.larsen@eldorado.org.br \
--cc=farosas@linux.ibm.com \
--cc=fernando.valle@eldorado.org.br \
--cc=lucas.araujo@eldorado.org.br \
--cc=luis.pires@eldorado.org.br \
--cc=matheus.ferst@eldorado.org.br \
--cc=qemu-devel@nongnu.org \
--cc=qemu-ppc@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.