[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [RFC v1 13/13] target-ppc: introduce opc4 for Expanded Opcode
From: |
Nikunj A Dadhania |
Subject: |
[Qemu-ppc] [RFC v1 13/13] target-ppc: introduce opc4 for Expanded Opcode |
Date: |
Mon, 18 Jul 2016 22:35:17 +0530 |
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>
---
target-ppc/translate.c | 73 +++++++++++++++++++++++++------
target-ppc/translate_init.c | 103 ++++++++++++++++++++++++++++++++------------
2 files changed, 136 insertions(+), 40 deletions(-)
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 6c5a4a6..733d68d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -40,6 +40,7 @@
/* Include definitions for instructions classes and implementations flags */
//#define PPC_DEBUG_DISAS
//#define DO_PPC_STATISTICS
+//#define PPC_DUMP_CPU
#ifdef PPC_DEBUG_DISAS
# define LOG_DISAS(...) qemu_log_mask(CPU_LOG_TB_IN_ASM, ## __VA_ARGS__)
@@ -367,12 +368,15 @@ 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];
+ unsigned char pad[4];
#else
- unsigned char pad[1];
+ unsigned char pad[4]; /* 4-byte pad to maintain pad in opcode table */
#endif
opc_handler_t handler;
const char *oname;
@@ -452,6 +456,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,6 +595,7 @@ EXTRACT_HELPER(SP, 19, 2);
.opc1 = op1, \
.opc2 = op2, \
.opc3 = op3, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl, \
@@ -604,6 +611,7 @@ EXTRACT_HELPER(SP, 19, 2);
.opc1 = op1, \
.opc2 = op2, \
.opc3 = op3, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl1, \
@@ -620,6 +628,7 @@ EXTRACT_HELPER(SP, 19, 2);
.opc1 = op1, \
.opc2 = op2, \
.opc3 = op3, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl, \
@@ -630,12 +639,29 @@ 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, \
+ .pad = { 0, }, \
+ .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, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl, \
@@ -650,6 +676,7 @@ EXTRACT_HELPER(SP, 19, 2);
.opc1 = op1, \
.opc2 = op2, \
.opc3 = op3, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl1, \
@@ -665,6 +692,7 @@ EXTRACT_HELPER(SP, 19, 2);
.opc1 = op1, \
.opc2 = op2, \
.opc3 = op3, \
+ .opc4 = 0xff, \
.pad = { 0, }, \
.handler = { \
.inval1 = invl, \
@@ -674,6 +702,21 @@ 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, \
+ .pad = { 0, }, \
+ .handler = { \
+ .inval1 = invl, \
+ .type = _typ, \
+ .type2 = _typ2, \
+ .handler = &gen_##name, \
+ }, \
+ .oname = stringify(name), \
+}
#endif
/* SPR load/store helpers */
@@ -11946,9 +11989,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)];
@@ -11958,14 +12002,19 @@ 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;
@@ -11977,10 +12026,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",
+ "%02x - %02x - %02x - %02x (%08x) "
TARGET_FMT_lx "\n",
ctx.opcode & inval, opc1(ctx.opcode),
opc2(ctx.opcode), opc3(ctx.opcode),
- ctx.opcode, ctx.nip - 4);
+ opc4(ctx.opcode), ctx.opcode, ctx.nip - 4);
gen_inval_exception(ctxp, POWERPC_EXCP_INVAL_INVAL);
break;
}
@@ -12006,9 +12055,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",
+ fprintf(stderr, "Opcode %02x %02x %02x %02x (%08x) leaked
temporaries\n",
opc1(ctx.opcode), opc2(ctx.opcode), opc3(ctx.opcode),
- ctx.opcode);
+ opc4(ctx.opcode), ctx.opcode);
exit(1);
}
}
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index d207f68..7c723e9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9252,13 +9252,45 @@ 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)
@@ -9334,7 +9366,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 */
@@ -9354,34 +9386,49 @@ 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);
+ }
}
}
}
--
2.7.4
- Re: [Qemu-ppc] [RFC v1 09/13] target-ppc: add cmpeqb instruction, (continued)
- Re: [Qemu-ppc] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Nikunj A Dadhania, 2016/07/18
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Richard Henderson, 2016/07/21
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Nikunj A Dadhania, 2016/07/21
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Nikunj A Dadhania, 2016/07/22
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Richard Henderson, 2016/07/22
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Nikunj A Dadhania, 2016/07/23
- Re: [Qemu-ppc] [Qemu-devel] [RFC v1 09/13] target-ppc: add cmpeqb instruction, Richard Henderson, 2016/07/23
Re: [Qemu-ppc] [RFC v1 09/13] target-ppc: add cmpeqb instruction, David Gibson, 2016/07/22
[Qemu-ppc] [RFC v1 12/13] target-ppc: add maddhd and maddhdu instruction, Nikunj A Dadhania, 2016/07/18
[Qemu-ppc] [RFC v1 13/13] target-ppc: introduce opc4 for Expanded Opcode,
Nikunj A Dadhania <=
Re: [Qemu-ppc] [Qemu-devel] [RFC v1 13/13] target-ppc: introduce opc4 for Expanded Opcode, Bharata B Rao, 2016/07/22