From patchwork Mon Jun 15 17:24:47 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 484479 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id D7E541401DA for ; Tue, 16 Jun 2015 03:43:02 +1000 (AEST) Received: from localhost ([::1]:35780 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4YPU-00058F-S6 for incoming@patchwork.ozlabs.org; Mon, 15 Jun 2015 13:43:00 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:32772) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4Y8K-0007m1-F0 for qemu-devel@nongnu.org; Mon, 15 Jun 2015 13:25:18 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z4Y8E-0001TT-5G for qemu-devel@nongnu.org; Mon, 15 Jun 2015 13:25:16 -0400 Received: from mnementh.archaic.org.uk ([2001:8b0:1d0::1]:34471) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z4Y8D-0001AA-KM for qemu-devel@nongnu.org; Mon, 15 Jun 2015 13:25:10 -0400 Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1Z4Y83-0003Wd-9E for qemu-devel@nongnu.org; Mon, 15 Jun 2015 18:24:59 +0100 From: Peter Maydell To: qemu-devel@nongnu.org Date: Mon, 15 Jun 2015 18:24:47 +0100 Message-Id: <1434389098-13430-18-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1434389098-13430-1-git-send-email-peter.maydell@linaro.org> References: <1434389098-13430-1-git-send-email-peter.maydell@linaro.org> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:8b0:1d0::1 Subject: [Qemu-devel] [PULL 17/28] target-arm: Add the THUMB_DSP feature X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: "Aurelio C. Remonda" Create an ARM_FEATURE_THUMB_DSP controlling the Thumb encodings of the 85 DSP instructions (these are all Thumb2). This is enabled for all non-M-profile CPUs with Thumb2 support, as the instructions are mandatory for R and A profiles. On M profile they are optional and not present in the Cortex-M3 (though they are in the M4). The effect of this commit is that we will now treat the DSP encodings as illegal instructions on M3, when previously we incorrectly implemented them. Signed-off-by: Aurelio C. Remonda Message-id: 1434311355-26554-1-git-send-email-aurelioremonda@gmail.com [PMM: added clz/crc32/crc32c and default case to the early-decode switch; minor format/spacing fixups; reworded commit message a bit] Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- target-arm/cpu.c | 4 ++ target-arm/cpu.h | 1 + target-arm/translate.c | 112 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 107 insertions(+), 10 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 34990ac..6fa51f4 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -545,6 +545,10 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) if (arm_feature(env, ARM_FEATURE_CBAR_RO)) { set_feature(env, ARM_FEATURE_CBAR); } + if (arm_feature(env, ARM_FEATURE_THUMB2) && + !arm_feature(env, ARM_FEATURE_M)) { + set_feature(env, ARM_FEATURE_THUMB_DSP); + } if (cpu->reset_hivecs) { cpu->reset_sctlr |= (1 << 13); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index 7c1d95c..c9d2330 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -889,6 +889,7 @@ enum arm_features { ARM_FEATURE_V8_SHA1, /* implements SHA1 part of v8 Crypto Extensions */ ARM_FEATURE_V8_SHA256, /* implements SHA256 part of v8 Crypto Extensions */ ARM_FEATURE_V8_PMULL, /* implements PMULL part of v8 Crypto Extensions */ + ARM_FEATURE_THUMB_DSP, /* DSP insns supported in the Thumb encodings */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/translate.c b/target-arm/translate.c index 39692d7..125b6da 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -9444,6 +9444,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw op = (insn >> 21) & 0xf; if (op == 6) { + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } /* Halfword pack. */ tmp = load_reg(s, rn); tmp2 = load_reg(s, rm); @@ -9508,6 +9511,27 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw store_reg_bx(s, rd, tmp); break; case 1: /* Sign/zero extend. */ + op = (insn >> 20) & 7; + switch (op) { + case 0: /* SXTAH, SXTH */ + case 1: /* UXTAH, UXTH */ + case 4: /* SXTAB, SXTB */ + case 5: /* UXTAB, UXTB */ + break; + case 2: /* SXTAB16, SXTB16 */ + case 3: /* UXTAB16, UXTB16 */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } + break; + default: + goto illegal_op; + } + if (rn != 15) { + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } + } tmp = load_reg(s, rm); shift = (insn >> 4) & 3; /* ??? In many cases it's not necessary to do a @@ -9522,7 +9546,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw case 3: gen_uxtb16(tmp); break; case 4: gen_sxtb(tmp); break; case 5: gen_uxtb(tmp); break; - default: goto illegal_op; + default: + g_assert_not_reached(); } if (rn != 15) { tmp2 = load_reg(s, rn); @@ -9536,6 +9561,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw store_reg(s, rd, tmp); break; case 2: /* SIMD add/subtract. */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } op = (insn >> 20) & 7; shift = (insn >> 4) & 7; if ((op & 3) == 3 || (shift & 3) == 3) @@ -9550,6 +9578,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); if (op < 4) { /* Saturating add/subtract. */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } tmp = load_reg(s, rn); tmp2 = load_reg(s, rm); if (op & 1) @@ -9560,6 +9591,31 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2); tcg_temp_free_i32(tmp2); } else { + switch (op) { + case 0x0a: /* rbit */ + case 0x08: /* rev */ + case 0x09: /* rev16 */ + case 0x0b: /* revsh */ + case 0x18: /* clz */ + break; + case 0x10: /* sel */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } + break; + case 0x20: /* crc32/crc32c */ + case 0x21: + case 0x22: + case 0x28: + case 0x29: + case 0x2a: + if (!arm_dc_feature(s, ARM_FEATURE_CRC)) { + goto illegal_op; + } + break; + default: + goto illegal_op; + } tmp = load_reg(s, rn); switch (op) { case 0x0a: /* rbit */ @@ -9596,10 +9652,6 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw uint32_t sz = op & 0x3; uint32_t c = op & 0x8; - if (!arm_dc_feature(s, ARM_FEATURE_CRC)) { - goto illegal_op; - } - tmp2 = load_reg(s, rm); if (sz == 0) { tcg_gen_andi_i32(tmp2, tmp2, 0xff); @@ -9617,12 +9669,26 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw break; } default: - goto illegal_op; + g_assert_not_reached(); } } store_reg(s, rd, tmp); break; case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */ + switch ((insn >> 20) & 7) { + case 0: /* 32 x 32 -> 32 */ + case 7: /* Unsigned sum of absolute differences. */ + break; + case 1: /* 16 x 16 -> 32 */ + case 2: /* Dual multiply add. */ + case 3: /* 32 * 16 -> 32msb */ + case 4: /* Dual multiply subtract. */ + case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + goto illegal_op; + } + break; + } op = (insn >> 4) & 0xf; tmp = load_reg(s, rn); tmp2 = load_reg(s, rm); @@ -9735,6 +9801,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw store_reg(s, rd, tmp); } else if ((op & 0xe) == 0xc) { /* Dual multiply accumulate long. */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + goto illegal_op; + } if (op & 1) gen_swap_half(tmp2); gen_smul_dual(tmp, tmp2); @@ -9758,6 +9829,11 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } else { if (op & 8) { /* smlalxy */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + tcg_temp_free_i32(tmp2); + tcg_temp_free_i32(tmp); + goto illegal_op; + } gen_mulxy(tmp, tmp2, op & 2, op & 1); tcg_temp_free_i32(tmp2); tmp64 = tcg_temp_new_i64(); @@ -9770,6 +9846,10 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw } if (op & 4) { /* umaal */ + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + tcg_temp_free_i64(tmp64); + goto illegal_op; + } gen_addq_lo(s, tmp64, rs); gen_addq_lo(s, tmp64, rd); } else if (op & 0x40) { @@ -10034,16 +10114,28 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw tmp2 = tcg_const_i32(imm); if (op & 4) { /* Unsigned. */ - if ((op & 1) && shift == 0) + if ((op & 1) && shift == 0) { + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + goto illegal_op; + } gen_helper_usat16(tmp, cpu_env, tmp, tmp2); - else + } else { gen_helper_usat(tmp, cpu_env, tmp, tmp2); + } } else { /* Signed. */ - if ((op & 1) && shift == 0) + if ((op & 1) && shift == 0) { + if (!arm_dc_feature(s, ARM_FEATURE_THUMB_DSP)) { + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + goto illegal_op; + } gen_helper_ssat16(tmp, cpu_env, tmp, tmp2); - else + } else { gen_helper_ssat(tmp, cpu_env, tmp, tmp2); + } } tcg_temp_free_i32(tmp2); break;