diff options
author | Nikunj A Dadhania <nikunj@linux.vnet.ibm.com> | 2016-07-26 17:28:38 +0530 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2016-09-07 12:33:33 +1000 |
commit | 323ad19bcc601d3ec9cb6f0f5b4d67b602fc519e (patch) | |
tree | 3fa4719ccc6105cf8b29592fe69b2b39cd63a0c7 /target-ppc/translate.c | |
parent | 5f29cc829225f777ca4697cb955572feebaf0748 (diff) |
target-ppc: introduce opc4 for Expanded Opcode
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 <nikunj@linux.vnet.ibm.com>
[dwg: Trivial checkpatch fixup]
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target-ppc/translate.c')
-rw-r--r-- | target-ppc/translate.c | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 0b21ea28ac..4036bc3442 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 */ @@ -11905,9 +11937,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)]; @@ -11917,14 +11950,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; @@ -11936,9 +11975,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; @@ -11965,9 +12005,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); } } |