From patchwork Thu Feb 3 19:43:25 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 81707 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id A466AB70E3 for ; Fri, 4 Feb 2011 07:03:24 +1100 (EST) Received: from localhost ([127.0.0.1]:51284 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pl5Oj-0006C7-Of for incoming@patchwork.ozlabs.org; Thu, 03 Feb 2011 15:03:21 -0500 Received: from [140.186.70.92] (port=45282 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pl57a-0004oM-Mn for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:45:44 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pl55a-0002OP-3c for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:43:35 -0500 Received: from mnementh.archaic.org.uk ([81.2.115.146]:26905) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pl55Z-0002NL-Pj for qemu-devel@nongnu.org; Thu, 03 Feb 2011 14:43:34 -0500 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.69) (envelope-from ) id 1Pl55R-0000nd-5a; Thu, 03 Feb 2011 19:43:25 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Date: Thu, 3 Feb 2011 19:43:25 +0000 Message-Id: <1296762205-3043-5-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1296762205-3043-1-git-send-email-peter.maydell@linaro.org> References: <1296762205-3043-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-Received-From: 81.2.115.146 Cc: patches@linaro.org Subject: [Qemu-devel] [PATCH 4/4] target-arm: Fix decoding of Thumb preload and hint space X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Refine the decoding of the Thumb preload and hint space, so we UNDEF on the patterns that are supposed to UNDEF rather than NOP. We also move the tests for this space earlier, so we don't emit harmless but unnecessary address generation code for preload hints (which by their nature are likely to be in hot code paths). Signed-off-by: Peter Maydell --- target-arm/translate.c | 70 +++++++++++++++++++++++++++++++++--------------- 1 files changed, 48 insertions(+), 22 deletions(-) diff --git a/target-arm/translate.c b/target-arm/translate.c index b742394..b445355 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -8308,6 +8308,42 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) goto illegal_op; break; } + op = ((insn >> 21) & 3) | ((insn >> 22) & 4); + if (rs == 15) { + if (!(insn & (1 << 20))) { + goto illegal_op; + } + if (op != 2) { + /* Byte or halfword load space with dest == r15 : memory hints. + * Catch them early so we don't emit pointless addressing code. + * This space is a mix of: + * PLD/PLDW/PLI, which we implement as NOPs (note that unlike + * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP + * cores) + * unallocated hints, which must be treated as NOPs + * UNPREDICTABLE space, which we NOP or UNDEF depending on + * which is easiest for the decoding logic + * Some space which must UNDEF + */ + int op1 = (insn >> 23) & 3; + int op2 = (insn >> 6) & 0x3f; + if (op & 2) { + goto illegal_op; + } + if (rn == 15) { + /* UNPREDICTABLE or unallocated hint */ + return 0; + } + if (op1 & 1) { + return 0; /* PLD* or unallocated hint */ + } + if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) { + return 0; /* PLD* or unallocated hint */ + } + /* UNDEF space, or an UNPREDICTABLE */ + return 1; + } + } user = IS_USER(s); if (rn == 15) { addr = new_tmp(); @@ -8326,9 +8362,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) imm = insn & 0xfff; tcg_gen_addi_i32(addr, addr, imm); } else { - op = (insn >> 8) & 7; imm = insn & 0xff; - switch (op) { + switch ((insn >> 8) & 7) { case 0: case 8: /* Shifted Register. */ shift = (insn >> 4) & 0xf; if (shift > 3) @@ -8365,32 +8400,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } } } - op = ((insn >> 21) & 3) | ((insn >> 22) & 4); if (insn & (1 << 20)) { /* Load. */ - if (rs == 15 && op != 2) { - if (op & 2) - goto illegal_op; - /* Memory hint. Implemented as NOP. */ + switch (op) { + case 0: tmp = gen_ld8u(addr, user); break; + case 4: tmp = gen_ld8s(addr, user); break; + case 1: tmp = gen_ld16u(addr, user); break; + case 5: tmp = gen_ld16s(addr, user); break; + case 2: tmp = gen_ld32(addr, user); break; + default: goto illegal_op; + } + if (rs == 15) { + gen_bx(s, tmp); } else { - switch (op) { - case 0: tmp = gen_ld8u(addr, user); break; - case 4: tmp = gen_ld8s(addr, user); break; - case 1: tmp = gen_ld16u(addr, user); break; - case 5: tmp = gen_ld16s(addr, user); break; - case 2: tmp = gen_ld32(addr, user); break; - default: goto illegal_op; - } - if (rs == 15) { - gen_bx(s, tmp); - } else { - store_reg(s, rs, tmp); - } + store_reg(s, rs, tmp); } } else { /* Store. */ - if (rs == 15) - goto illegal_op; tmp = load_reg(s, rs); switch (op) { case 0: gen_st8(tmp, addr, user); break;