[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v4 15/15] target-ppc: introduce opc4 for Expande
From: |
David Gibson |
Subject: |
Re: [Qemu-devel] [PATCH v4 15/15] target-ppc: introduce opc4 for Expanded Opcode |
Date: |
Wed, 27 Jul 2016 15:31:02 +1000 |
User-agent: |
Mutt/1.6.2 (2016-07-01) |
On Tue, Jul 26, 2016 at 05:28:38PM +0530, Nikunj A Dadhania wrote:
> ISA 3.0 has introduced EO - Expanded Opcode. Introduce third level
> indirect opcode table and corresponding parsing routines.
>
> EO (11:12) Expanded opcode field
> Formats: XX1
>
> EO (11:15) Expanded opcode field
> Formats: VX, X, XX2
>
> Signed-off-by: Nikunj A Dadhania <address@hidden>
Reviewed-by: David Gibson <address@hidden>
> ---
> target-ppc/translate.c | 82 ++++++++++++++++++++--------
> target-ppc/translate_init.c | 126
> ++++++++++++++++++++++++++++++++------------
> 2 files changed, 154 insertions(+), 54 deletions(-)
>
> diff --git a/target-ppc/translate.c b/target-ppc/translate.c
> index ec7064f..d522566 100644
> --- a/target-ppc/translate.c
> +++ b/target-ppc/translate.c
> @@ -367,12 +367,13 @@ GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type,
> PPC_NONE)
> #define GEN_HANDLER2_E(name, onam, opc1, opc2, opc3, inval, type, type2)
> \
> GEN_OPCODE2(name, onam, opc1, opc2, opc3, inval, type, type2)
>
> +#define GEN_HANDLER_E_2(name, opc1, opc2, opc3, opc4, inval, type, type2)
> \
> +GEN_OPCODE3(name, opc1, opc2, opc3, opc4, inval, type, type2)
> +
> typedef struct opcode_t {
> - unsigned char opc1, opc2, opc3;
> + unsigned char opc1, opc2, opc3, opc4;
> #if HOST_LONG_BITS == 64 /* Explicitly align to 64 bits */
> - unsigned char pad[5];
> -#else
> - unsigned char pad[1];
> + unsigned char pad[4];
> #endif
> opc_handler_t handler;
> const char *oname;
> @@ -452,6 +453,8 @@ EXTRACT_HELPER(opc1, 26, 6);
> EXTRACT_HELPER(opc2, 1, 5);
> /* Opcode part 3 */
> EXTRACT_HELPER(opc3, 6, 5);
> +/* Opcode part 4 */
> +EXTRACT_HELPER(opc4, 16, 5);
> /* Update Cr0 flags */
> EXTRACT_HELPER(Rc, 0, 1);
> /* Update Cr6 flags (Altivec) */
> @@ -589,7 +592,7 @@ EXTRACT_HELPER(SP, 19, 2);
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl,
> \
> .type = _typ,
> \
> @@ -604,7 +607,7 @@ EXTRACT_HELPER(SP, 19, 2);
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl1,
> \
> .inval2 = invl2,
> \
> @@ -620,7 +623,7 @@ EXTRACT_HELPER(SP, 19, 2);
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl,
> \
> .type = _typ,
> \
> @@ -630,13 +633,28 @@ EXTRACT_HELPER(SP, 19, 2);
> },
> \
> .oname = onam,
> \
> }
> +#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2)
> \
> +{
> \
> + .opc1 = op1,
> \
> + .opc2 = op2,
> \
> + .opc3 = op3,
> \
> + .opc4 = op4,
> \
> + .handler = {
> \
> + .inval1 = invl,
> \
> + .type = _typ,
> \
> + .type2 = _typ2,
> \
> + .handler = &gen_##name,
> \
> + .oname = stringify(name),
> \
> + },
> \
> + .oname = stringify(name),
> \
> +}
> #else
> #define GEN_OPCODE(name, op1, op2, op3, invl, _typ, _typ2)
> \
> {
> \
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl,
> \
> .type = _typ,
> \
> @@ -650,7 +668,7 @@ EXTRACT_HELPER(SP, 19, 2);
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl1,
> \
> .inval2 = invl2,
> \
> @@ -665,7 +683,7 @@ EXTRACT_HELPER(SP, 19, 2);
> .opc1 = op1,
> \
> .opc2 = op2,
> \
> .opc3 = op3,
> \
> - .pad = { 0, },
> \
> + .opc4 = 0xff,
> \
> .handler = {
> \
> .inval1 = invl,
> \
> .type = _typ,
> \
> @@ -674,6 +692,20 @@ EXTRACT_HELPER(SP, 19, 2);
> },
> \
> .oname = onam,
> \
> }
> +#define GEN_OPCODE3(name, op1, op2, op3, op4, invl, _typ, _typ2)
> \
> +{
> \
> + .opc1 = op1,
> \
> + .opc2 = op2,
> \
> + .opc3 = op3,
> \
> + .opc4 = op4,
> \
> + .handler = {
> \
> + .inval1 = invl,
> \
> + .type = _typ,
> \
> + .type2 = _typ2,
> \
> + .handler = &gen_##name,
> \
> + },
> \
> + .oname = stringify(name),
> \
> +}
> #endif
>
> /* SPR load/store helpers */
> @@ -11906,9 +11938,10 @@ void gen_intermediate_code(CPUPPCState *env, struct
> TranslationBlock *tb)
> } else {
> ctx.opcode = cpu_ldl_code(env, ctx.nip);
> }
> - LOG_DISAS("translate opcode %08x (%02x %02x %02x) (%s)\n",
> - ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
> - opc3(ctx.opcode), ctx.le_mode ? "little" : "big");
> + LOG_DISAS("translate opcode %08x (%02x %02x %02x %02x) (%s)\n",
> + ctx.opcode, opc1(ctx.opcode), opc2(ctx.opcode),
> + opc3(ctx.opcode), opc4(ctx.opcode),
> + ctx.le_mode ? "little" : "big");
> ctx.nip += 4;
> table = env->opcodes;
> handler = table[opc1(ctx.opcode)];
> @@ -11918,14 +11951,20 @@ void gen_intermediate_code(CPUPPCState *env, struct
> TranslationBlock *tb)
> if (is_indirect_opcode(handler)) {
> table = ind_table(handler);
> handler = table[opc3(ctx.opcode)];
> + if (is_indirect_opcode(handler)) {
> + table = ind_table(handler);
> + handler = table[opc4(ctx.opcode)];
> + }
> }
> }
> /* Is opcode *REALLY* valid ? */
> if (unlikely(handler->handler == &gen_invalid)) {
> qemu_log_mask(LOG_GUEST_ERROR, "invalid/unsupported opcode: "
> - "%02x - %02x - %02x (%08x) " TARGET_FMT_lx " %d\n",
> + "%02x - %02x - %02x - %02x (%08x) "
> + TARGET_FMT_lx " %d\n",
> opc1(ctx.opcode), opc2(ctx.opcode),
> - opc3(ctx.opcode), ctx.opcode, ctx.nip - 4,
> (int)msr_ir);
> + opc3(ctx.opcode), opc4(ctx.opcode),
> + ctx.opcode, ctx.nip - 4, (int)msr_ir);
> } else {
> uint32_t inval;
>
> @@ -11937,9 +11976,10 @@ void gen_intermediate_code(CPUPPCState *env, struct
> TranslationBlock *tb)
>
> if (unlikely((ctx.opcode & inval) != 0)) {
> qemu_log_mask(LOG_GUEST_ERROR, "invalid bits: %08x for
> opcode: "
> - "%02x - %02x - %02x (%08x) " TARGET_FMT_lx
> "\n",
> - ctx.opcode & inval, opc1(ctx.opcode),
> - opc2(ctx.opcode), opc3(ctx.opcode),
> + "%02x - %02x - %02x - %02x (%08x) "
> + TARGET_FMT_lx "\n", ctx.opcode & inval,
> + opc1(ctx.opcode), opc2(ctx.opcode),
> + opc3(ctx.opcode), opc4(ctx.opcode),
> ctx.opcode, ctx.nip - 4);
> gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
> break;
> @@ -11966,9 +12006,9 @@ void gen_intermediate_code(CPUPPCState *env, struct
> TranslationBlock *tb)
> break;
> }
> if (tcg_check_temp_count()) {
> - fprintf(stderr, "Opcode %02x %02x %02x (%08x) leaked
> temporaries\n",
> - opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
> - ctx.opcode);
> + fprintf(stderr, "Opcode %02x %02x %02x %02x (%08x) leaked "
> + "temporaries\n", opc1(ctx.opcode), opc2(ctx.opcode),
> + opc3(ctx.opcode), opc4(ctx.opcode), ctx.opcode);
> exit(1);
> }
> }
> diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
> index 0d8cff1..f627cfe 100644
> --- a/target-ppc/translate_init.c
> +++ b/target-ppc/translate_init.c
> @@ -9253,13 +9253,47 @@ static int register_dblind_insn (opc_handler_t
> **ppc_opcodes,
> 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 (register_dblind_insn(ppc_opcodes, insn->opc1, insn->opc2,
> - insn->opc3, &insn->handler) < 0)
> - return -1;
> + 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)
> @@ -9335,7 +9369,7 @@ static void dump_ppc_insns (CPUPPCState *env)
> {
> opc_handler_t **table, *handler;
> const char *p, *q;
> - uint8_t opc1, opc2, opc3;
> + uint8_t opc1, opc2, opc3, opc4;
>
> printf("Instructions set:\n");
> /* opc1 is 6 bits long */
> @@ -9355,34 +9389,50 @@ static void dump_ppc_insns (CPUPPCState *env)
> for (opc3 = 0; opc3 < PPC_CPU_INDIRECT_OPCODES_LEN;
> opc3++) {
> handler = table[opc3];
> - 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),
> + 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);
> }
> - if (strcmp(p + 1, q) != 0) {
> - /* Second instruction */
> + }
> + } 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 << 1) | 1, opc3, opc1,
> - (opc3 << 6) | (opc2 << 1) | 1,
> - p + 1);
> + 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);
> + }
> }
> }
> }
> @@ -9858,8 +9908,8 @@ static void ppc_cpu_unrealizefn(DeviceState *dev, Error
> **errp)
> {
> PowerPCCPU *cpu = POWERPC_CPU(dev);
> CPUPPCState *env = &cpu->env;
> - opc_handler_t **table;
> - int i, j;
> + opc_handler_t **table, **table_2;
> + int i, j, k;
>
> cpu_exec_exit(CPU(dev));
>
> @@ -9870,10 +9920,20 @@ static void ppc_cpu_unrealizefn(DeviceState *dev,
> Error **errp)
> if (is_indirect_opcode(env->opcodes[i])) {
> table = ind_table(env->opcodes[i]);
> for (j = 0; j < PPC_CPU_INDIRECT_OPCODES_LEN; j++) {
> - if (table[j] != &invalid_handler &&
> - is_indirect_opcode(table[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));
> + ~PPC_INDIRECT));
> }
> }
> g_free((opc_handler_t *)((uintptr_t)env->opcodes[i] &
--
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
signature.asc
Description: PGP signature