From patchwork Mon Jul 18 17:05:17 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Nikunj A. Dadhania" X-Patchwork-Id: 9234969 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 3C7BF6075D for ; Mon, 18 Jul 2016 17:46:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2EB1320453 for ; Mon, 18 Jul 2016 17:46:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 235D6205A8; Mon, 18 Jul 2016 17:46:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3F6A120453 for ; Mon, 18 Jul 2016 17:46:55 +0000 (UTC) Received: from localhost ([::1]:49387 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPCd4-0005tn-A8 for patchwork-qemu-devel@patchwork.kernel.org; Mon, 18 Jul 2016 13:46:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44352) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPBzM-0005Lq-I3 for qemu-devel@nongnu.org; Mon, 18 Jul 2016 13:05:56 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bPBzH-0006n5-ID for qemu-devel@nongnu.org; Mon, 18 Jul 2016 13:05:52 -0400 Received: from mx0b-001b2d01.pphosted.com ([148.163.158.5]:13030 helo=mx0a-001b2d01.pphosted.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bPBzH-0006mv-CK for qemu-devel@nongnu.org; Mon, 18 Jul 2016 13:05:47 -0400 Received: from pps.filterd (m0098413.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.11/8.16.0.11) with SMTP id u6IGx5tk076979 for ; Mon, 18 Jul 2016 13:05:47 -0400 Received: from e28smtp07.in.ibm.com (e28smtp07.in.ibm.com [125.16.236.7]) by mx0b-001b2d01.pphosted.com with ESMTP id 2482asy7pp-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Mon, 18 Jul 2016 13:05:46 -0400 Received: from localhost by e28smtp07.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 18 Jul 2016 22:35:43 +0530 Received: from d28dlp01.in.ibm.com (9.184.220.126) by e28smtp07.in.ibm.com (192.168.1.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 18 Jul 2016 22:35:40 +0530 X-IBM-Helo: d28dlp01.in.ibm.com X-IBM-MailFrom: nikunj@linux.vnet.ibm.com X-IBM-RcptTo: qemu-devel@nongnu.org;qemu-ppc@nongnu.org Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp01.in.ibm.com (Postfix) with ESMTP id 5EE4FE0040; Mon, 18 Jul 2016 22:39:46 +0530 (IST) Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay03.in.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id u6IH5doo3080560; Mon, 18 Jul 2016 22:35:39 +0530 Received: from d28av03.in.ibm.com (localhost [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id u6IH5ahJ022412; Mon, 18 Jul 2016 22:35:38 +0530 Received: from abhimanyu.in.ibm.com ([9.124.211.241]) by d28av03.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id u6IH5JJp021621; Mon, 18 Jul 2016 22:35:35 +0530 From: Nikunj A Dadhania To: qemu-ppc@nongnu.org, david@gibson.dropbear.id.au Date: Mon, 18 Jul 2016 22:35:17 +0530 X-Mailer: git-send-email 2.7.4 In-Reply-To: <1468861517-2508-1-git-send-email-nikunj@linux.vnet.ibm.com> References: <1468861517-2508-1-git-send-email-nikunj@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 16071817-0052-0000-0000-000002A0BC19 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 16071817-0053-0000-0000-00000D7D1CB4 Message-Id: <1468861517-2508-14-git-send-email-nikunj@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2016-07-18_07:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1604210000 definitions=main-1607180188 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [generic] X-Received-From: 148.163.158.5 Subject: [Qemu-devel] [RFC v1 13/13] target-ppc: introduce opc4 for Expanded Opcode X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, nikunj@linux.vnet.ibm.com, aneesh.kumar@linux.vnet.ibm.com Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP 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 --- 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); + } } } }