From patchwork Tue Mar 25 16:27:57 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 27042 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-ve0-f197.google.com (mail-ve0-f197.google.com [209.85.128.197]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id A4C8620539 for ; Tue, 25 Mar 2014 16:43:11 +0000 (UTC) Received: by mail-ve0-f197.google.com with SMTP id pa12sf1694886veb.4 for ; Tue, 25 Mar 2014 09:43:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:date :message-id:cc:subject:precedence:list-id:list-unsubscribe :list-archive:list-post:list-help:list-subscribe:errors-to:sender :x-original-sender:x-original-authentication-results:mailing-list; bh=+uGoFJVbBP52yvCGz0qMIqy6Rd0jgp0MVwkrRzKwYxg=; b=caWtNkkylb2ToHfjG6y4YRYzmOLtWKT0wRmhFLut48u2KQwrENy68QHaoPDEbFPSWs Qr+nc4MtWoEihMGTZt850rcaS5d/ZC45hp9KwMa3EEMataikqpR4KTIlwQGklBCT6QcB Lx1vTK29jCf2I4wIbdtYM5XJecR1xRg5Bx42Rn+AwQNySLMjkwUi/GQ2HsWwCaonYbfe tN/aw566Gbq3XtMP4FXYW5CyQXsk0yEI/5djXIDzVpu5yhaddMZyUPeH7lzoO5mNwxgg ZoziiaRsliAg96guQa4L0Dp1CFBd6UKItwN8eTD7McqorIt4tLdlo8KzTJPqOE44s/AG pwAw== X-Gm-Message-State: ALoCoQk/FM32cMrfTMV9kYIXW6Fk/D69sqGoCTBW/2rrzxLHw51hPQ/ZH/lPKj5Hfc3xDO6yHpPx X-Received: by 10.236.90.200 with SMTP id e48mr21572204yhf.28.1395765791401; Tue, 25 Mar 2014 09:43:11 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.21.213 with SMTP id 79ls268419qgl.35.gmail; Tue, 25 Mar 2014 09:43:11 -0700 (PDT) X-Received: by 10.52.173.165 with SMTP id bl5mr38713133vdc.13.1395765791309; Tue, 25 Mar 2014 09:43:11 -0700 (PDT) Received: from mail-ve0-f178.google.com (mail-ve0-f178.google.com [209.85.128.178]) by mx.google.com with ESMTPS id w5si3805934vcl.66.2014.03.25.09.43.11 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 09:43:11 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.128.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.178; Received: by mail-ve0-f178.google.com with SMTP id jw12so836114veb.23 for ; Tue, 25 Mar 2014 09:43:10 -0700 (PDT) X-Received: by 10.52.130.225 with SMTP id oh1mr13242954vdb.8.1395765790566; Tue, 25 Mar 2014 09:43:10 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.220.78.9 with SMTP id i9csp319321vck; Tue, 25 Mar 2014 09:43:10 -0700 (PDT) X-Received: by 10.140.94.68 with SMTP id f62mr28122845qge.64.1395765789837; Tue, 25 Mar 2014 09:43:09 -0700 (PDT) Received: from lists.gnu.org (lists.gnu.org. [2001:4830:134:3::11]) by mx.google.com with ESMTPS id f8si7565505qas.263.2014.03.25.09.43.09 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Tue, 25 Mar 2014 09:43:09 -0700 (PDT) Received-SPF: pass (google.com: domain of qemu-devel-bounces+patch=linaro.org@nongnu.org designates 2001:4830:134:3::11 as permitted sender) client-ip=2001:4830:134:3::11; Received: from localhost ([::1]:42862 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSURR-0006E6-2Q for patch@linaro.org; Tue, 25 Mar 2014 12:43:09 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:37745) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSUMi-0007Wc-FQ for qemu-devel@nongnu.org; Tue, 25 Mar 2014 12:42:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WSUCs-0002Lh-Gt for qemu-devel@nongnu.org; Tue, 25 Mar 2014 12:32:06 -0400 Received: from mail-wg0-f44.google.com ([74.125.82.44]:56977) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WSUCs-0002LV-8Z for qemu-devel@nongnu.org; Tue, 25 Mar 2014 12:28:06 -0400 Received: by mail-wg0-f44.google.com with SMTP id m15so482397wgh.3 for ; Tue, 25 Mar 2014 09:27:41 -0700 (PDT) X-Received: by 10.180.100.70 with SMTP id ew6mr22992792wib.57.1395764861419; Tue, 25 Mar 2014 09:27:41 -0700 (PDT) Received: from ards-macbook-pro.local (cag06-7-83-153-85-71.fbx.proxad.net. [83.153.85.71]) by mx.google.com with ESMTPSA id em1sm51913201wid.5.2014.03.25.09.27.40 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Mar 2014 09:27:40 -0700 (PDT) From: Ard Biesheuvel To: qemu-devel@nongnu.org, peter.maydell@linaro.org Date: Tue, 25 Mar 2014 17:27:57 +0100 Message-Id: <1395764877-10487-1-git-send-email-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 1.8.3.2 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 74.125.82.44 Cc: christoffer.dall@linaro.org, Ard Biesheuvel Subject: [Qemu-devel] [PATCH] target-arm: add support for v8 SHA1 and SHA256 instructions 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+patch=linaro.org@nongnu.org Sender: qemu-devel-bounces+patch=linaro.org@nongnu.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ard.biesheuvel@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.178 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 This adds support for the SHA1 and SHA256 instructions that are available on some v8 implementations of Aarch32. Signed-off-by: Ard Biesheuvel --- target-arm/cpu.c | 2 + target-arm/cpu.h | 2 + target-arm/crypto_helper.c | 257 +++++++++++++++++++++++++++++++++++++++++++-- target-arm/helper.h | 9 ++ target-arm/translate.c | 81 ++++++++++++++ 5 files changed, 344 insertions(+), 7 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index c32d8c4855b4..58c4584ac3bc 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -291,6 +291,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) set_feature(env, ARM_FEATURE_ARM_DIV); set_feature(env, ARM_FEATURE_LPAE); set_feature(env, ARM_FEATURE_V8_AES); + set_feature(env, ARM_FEATURE_V8_SHA1); + set_feature(env, ARM_FEATURE_V8_SHA256); } if (arm_feature(env, ARM_FEATURE_V7)) { set_feature(env, ARM_FEATURE_VAPA); diff --git a/target-arm/cpu.h b/target-arm/cpu.h index bf37cd60d0a2..f5039d8b0177 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -630,6 +630,8 @@ enum arm_features { ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */ ARM_FEATURE_CBAR, /* has cp15 CBAR */ ARM_FEATURE_CRC, /* ARMv8 CRC instructions */ + ARM_FEATURE_V8_SHA1, /* implements SHA1 part of v8 Crypto Extensions */ + ARM_FEATURE_V8_SHA256, /* implements SHA256 part of v8 Crypto Extensions */ }; static inline int arm_feature(CPUARMState *env, int feature) diff --git a/target-arm/crypto_helper.c b/target-arm/crypto_helper.c index f94be69ac596..211be36ebda8 100644 --- a/target-arm/crypto_helper.c +++ b/target-arm/crypto_helper.c @@ -1,7 +1,7 @@ /* * crypto_helper.c - emulate v8 Crypto Extensions instructions * - * Copyright (C) 2013 Linaro Ltd + * Copyright (C) 2013 - 2014 Linaro Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -15,9 +15,9 @@ #include "exec/exec-all.h" #include "helper.h" -union AES_STATE { +union CRYPTO_STATE { uint8_t bytes[16]; - uint32_t cols[4]; + uint32_t words[4]; uint64_t l[2]; }; @@ -99,11 +99,11 @@ void HELPER(crypto_aese)(CPUARMState *env, uint32_t rd, uint32_t rm, /* ShiftRows permutation vector for decryption */ { 0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3 }, }; - union AES_STATE rk = { .l = { + union CRYPTO_STATE rk = { .l = { float64_val(env->vfp.regs[rm]), float64_val(env->vfp.regs[rm + 1]) } }; - union AES_STATE st = { .l = { + union CRYPTO_STATE st = { .l = { float64_val(env->vfp.regs[rd]), float64_val(env->vfp.regs[rd + 1]) } }; @@ -260,7 +260,7 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, 0x92b479a7, 0x99b970a9, 0x84ae6bbb, 0x8fa362b5, 0xbe805d9f, 0xb58d5491, 0xa89a4f83, 0xa397468d, } }; - union AES_STATE st = { .l = { + union CRYPTO_STATE st = { .l = { float64_val(env->vfp.regs[rm]), float64_val(env->vfp.regs[rm + 1]) } }; @@ -269,7 +269,7 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, assert(decrypt < 2); for (i = 0; i < 16; i += 4) { - st.cols[i >> 2] = cpu_to_le32( + st.words[i >> 2] = cpu_to_le32( mc[decrypt][st.bytes[i]] ^ rol32(mc[decrypt][st.bytes[i + 1]], 8) ^ rol32(mc[decrypt][st.bytes[i + 2]], 16) ^ @@ -279,3 +279,246 @@ void HELPER(crypto_aesmc)(CPUARMState *env, uint32_t rd, uint32_t rm, env->vfp.regs[rd] = make_float64(st.l[0]); env->vfp.regs[rd + 1] = make_float64(st.l[1]); } + +/* + * SHA-1 logical functions + */ + +static uint32_t cho(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & (y ^ z)) ^ z; +} + +static uint32_t par(uint32_t x, uint32_t y, uint32_t z) +{ + return x ^ y ^ z; +} + +static uint32_t maj(uint32_t x, uint32_t y, uint32_t z) +{ + return (x & y) | ((x | y) & z); +} + +void HELPER(crypto_sha1_3reg)(CPUARMState *env, uint32_t rd, uint32_t rn, + uint32_t rm, uint32_t op) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE n = { .l = { + float64_val(env->vfp.regs[rn]), + float64_val(env->vfp.regs[rn + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + + if (op == 3) { /* sha1su0 */ + d.l[0] ^= d.l[1] ^ m.l[0]; + d.l[1] ^= n.l[0] ^ m.l[1]; + } else { + int i; + + for (i = 0; i < 4; i++) { + uint32_t t; + + switch (op) { + default: + /* not reached */ + case 0: /* sha1c */ + t = cho(d.words[1], d.words[2], d.words[3]); + break; + case 1: /* sha1p */ + t = par(d.words[1], d.words[2], d.words[3]); + break; + case 2: /* sha1m */ + t = maj(d.words[1], d.words[2], d.words[3]); + break; + } + t += rol32(d.words[0], 5) + n.words[0] + m.words[i]; + + n.words[0] = d.words[3]; + d.words[3] = d.words[2]; + d.words[2] = ror32(d.words[1], 2); + d.words[1] = d.words[0]; + d.words[0] = t; + } + } + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} + +void HELPER(crypto_sha1h)(CPUARMState *env, uint32_t rd, uint32_t rm) +{ + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + + m.words[0] = ror32(m.words[0], 2); + m.words[1] = m.words[2] = m.words[3] = 0; + + env->vfp.regs[rd] = make_float64(m.l[0]); + env->vfp.regs[rd + 1] = make_float64(m.l[1]); +} + +void HELPER(crypto_sha1su1)(CPUARMState *env, uint32_t rd, uint32_t rm) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + + d.words[0] = rol32(d.words[0] ^ m.words[1], 1); + d.words[1] = rol32(d.words[1] ^ m.words[2], 1); + d.words[2] = rol32(d.words[2] ^ m.words[3], 1); + d.words[3] = rol32(d.words[3] ^ d.words[0], 1); + + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} + +/* + * The SHA-256 logical functions, according to + * http://csrc.nist.gov/groups/STM/cavp/documents/shs/sha256-384-512.pdf + */ + +static uint32_t S0(uint32_t x) +{ + return ror32(x, 2) ^ ror32(x, 13) ^ ror32(x, 22); +} + +static uint32_t S1(uint32_t x) +{ + return ror32(x, 6) ^ ror32(x, 11) ^ ror32(x, 25); +} + +static uint32_t s0(uint32_t x) +{ + return ror32(x, 7) ^ ror32(x, 18) ^ (x >> 3); +} + +static uint32_t s1(uint32_t x) +{ + return ror32(x, 17) ^ ror32(x, 19) ^ (x >> 10); +} + +void HELPER(crypto_sha256h)(CPUARMState *env, uint32_t rd, uint32_t rn, + uint32_t rm) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE n = { .l = { + float64_val(env->vfp.regs[rn]), + float64_val(env->vfp.regs[rn + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + int i; + + for (i = 0; i < 4; i++) { + uint32_t t = cho(n.words[0], n.words[1], n.words[2]) + n.words[3] + + S1(n.words[0]) + m.words[i]; + + n.words[3] = n.words[2]; + n.words[2] = n.words[1]; + n.words[1] = n.words[0]; + n.words[0] = d.words[3] + t; + + t += maj(d.words[0], d.words[1], d.words[2]) + S0(d.words[0]); + + d.words[3] = d.words[2]; + d.words[2] = d.words[1]; + d.words[1] = d.words[0]; + d.words[0] = t; + } + + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} + +void HELPER(crypto_sha256h2)(CPUARMState *env, uint32_t rd, uint32_t rn, + uint32_t rm) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE n = { .l = { + float64_val(env->vfp.regs[rn]), + float64_val(env->vfp.regs[rn + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + int i; + + for (i = 0; i < 4; i++) { + uint32_t t = cho(d.words[0], d.words[1], d.words[2]) + d.words[3] + + S1(d.words[0]) + m.words[i]; + + d.words[3] = d.words[2]; + d.words[2] = d.words[1]; + d.words[1] = d.words[0]; + d.words[0] = n.words[3 - i] + t; + } + + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} + +void HELPER(crypto_sha256su0)(CPUARMState *env, uint32_t rd, uint32_t rm) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + + d.words[0] += s0(d.words[1]); + d.words[1] += s0(d.words[2]); + d.words[2] += s0(d.words[3]); + d.words[3] += s0(m.words[0]); + + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} + +void HELPER(crypto_sha256su1)(CPUARMState *env, uint32_t rd, uint32_t rn, + uint32_t rm) +{ + union CRYPTO_STATE d = { .l = { + float64_val(env->vfp.regs[rd]), + float64_val(env->vfp.regs[rd + 1]) + } }; + union CRYPTO_STATE n = { .l = { + float64_val(env->vfp.regs[rn]), + float64_val(env->vfp.regs[rn + 1]) + } }; + union CRYPTO_STATE m = { .l = { + float64_val(env->vfp.regs[rm]), + float64_val(env->vfp.regs[rm + 1]) + } }; + + d.words[0] += s1(m.words[2]) + n.words[1]; + d.words[1] += s1(m.words[3]) + n.words[2]; + d.words[2] += s1(d.words[0]) + n.words[3]; + d.words[3] += s1(d.words[1]) + m.words[0]; + + env->vfp.regs[rd] = make_float64(d.l[0]); + env->vfp.regs[rd + 1] = make_float64(d.l[1]); +} diff --git a/target-arm/helper.h b/target-arm/helper.h index 366c1b3ea59b..9024aef75157 100644 --- a/target-arm/helper.h +++ b/target-arm/helper.h @@ -512,6 +512,15 @@ DEF_HELPER_3(neon_qzip32, void, env, i32, i32) DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32) DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32) +DEF_HELPER_5(crypto_sha1_3reg, void, env, i32, i32, i32, i32) +DEF_HELPER_3(crypto_sha1h, void, env, i32, i32) +DEF_HELPER_3(crypto_sha1su1, void, env, i32, i32) + +DEF_HELPER_4(crypto_sha256h, void, env, i32, i32, i32) +DEF_HELPER_4(crypto_sha256h2, void, env, i32, i32, i32) +DEF_HELPER_3(crypto_sha256su0, void, env, i32, i32) +DEF_HELPER_4(crypto_sha256su1, void, env, i32, i32, i32) + DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) diff --git a/target-arm/translate.c b/target-arm/translate.c index 56e3b4bf7f2f..e79241402da8 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -4730,6 +4730,7 @@ static void gen_neon_narrow_op(int op, int u, int size, #define NEON_3R_VPMIN 21 #define NEON_3R_VQDMULH_VQRDMULH 22 #define NEON_3R_VPADD 23 +#define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */ #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */ #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */ #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */ @@ -4763,6 +4764,7 @@ static const uint8_t neon_3r_sizes[] = { [NEON_3R_VPMIN] = 0x7, [NEON_3R_VQDMULH_VQRDMULH] = 0x6, [NEON_3R_VPADD] = 0x7, + [NEON_3R_SHA] = 0xf, /* size field encodes op type */ [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */ [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */ [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */ @@ -4796,6 +4798,7 @@ static const uint8_t neon_3r_sizes[] = { #define NEON_2RM_VCEQ0 18 #define NEON_2RM_VCLE0 19 #define NEON_2RM_VCLT0 20 +#define NEON_2RM_SHA1H 21 #define NEON_2RM_VABS 22 #define NEON_2RM_VNEG 23 #define NEON_2RM_VCGT0_F 24 @@ -4812,6 +4815,7 @@ static const uint8_t neon_3r_sizes[] = { #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */ #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */ #define NEON_2RM_VSHLL 38 +#define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */ #define NEON_2RM_VRINTN 40 #define NEON_2RM_VRINTX 41 #define NEON_2RM_VRINTA 42 @@ -4872,6 +4876,7 @@ static const uint8_t neon_2rm_sizes[] = { [NEON_2RM_VCEQ0] = 0x7, [NEON_2RM_VCLE0] = 0x7, [NEON_2RM_VCLT0] = 0x7, + [NEON_2RM_SHA1H] = 0x4, [NEON_2RM_VABS] = 0x7, [NEON_2RM_VNEG] = 0x7, [NEON_2RM_VCGT0_F] = 0x4, @@ -4888,6 +4893,7 @@ static const uint8_t neon_2rm_sizes[] = { [NEON_2RM_VMOVN] = 0x7, [NEON_2RM_VQMOVN] = 0x7, [NEON_2RM_VSHLL] = 0x7, + [NEON_2RM_SHA1SU1] = 0x4, [NEON_2RM_VRINTN] = 0x4, [NEON_2RM_VRINTX] = 0x4, [NEON_2RM_VRINTA] = 0x4, @@ -4955,6 +4961,46 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins if (q && ((rd | rn | rm) & 1)) { return 1; } + /* + * The SHA-1/SHA-256 3-register instructions require special treatment + * here, as their size field is overloaded as an op type selector, and + * they all consume their input in a single pass. + */ + if (op == NEON_3R_SHA) { + if (!u) { /* SHA-1 */ + if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) { + return 1; + } + tmp = tcg_const_i32(rd); + tmp2 = tcg_const_i32(rn); + tmp3 = tcg_const_i32(rm); + tmp4 = tcg_const_i32(size); + gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4); + tcg_temp_free_i32(tmp4); + } else { /* SHA-256 */ + if (!arm_feature(env, ARM_FEATURE_V8_SHA256) || size == 3) { + return 1; + } + tmp = tcg_const_i32(rd); + tmp2 = tcg_const_i32(rn); + tmp3 = tcg_const_i32(rm); + switch (size) { + case 0: + gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3); + break; + case 1: + gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3); + break; + case 2: + gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3); + break; + } + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + tcg_temp_free_i32(tmp3); + return 0; + } if (size == 3 && op != NEON_3R_LOGIC) { /* 64-bit element instructions. */ for (pass = 0; pass < (q ? 2 : 1); pass++) { @@ -6430,6 +6476,41 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins tcg_temp_free_i32(tmp2); tcg_temp_free_i32(tmp3); break; + case NEON_2RM_SHA1H: + if (!arm_feature(env, ARM_FEATURE_V8_SHA1) + || ((rm | rd) & 1)) { + return 1; + } + tmp = tcg_const_i32(rd); + tmp2 = tcg_const_i32(rm); + + gen_helper_crypto_sha1h(cpu_env, tmp, tmp2); + + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + break; + case NEON_2RM_SHA1SU1: + if ((rm | rd) & 1) { + return 1; + } + /* bit 6: set -> SHA256SU0, cleared -> SHA1SU1 */ + if (extract32(insn, 6, 1)) { + if (!arm_feature(env, ARM_FEATURE_V8_SHA256)) { + return 1; + } + } else if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) { + return 1; + } + tmp = tcg_const_i32(rd); + tmp2 = tcg_const_i32(rm); + if (extract32(insn, 6, 1)) { + gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2); + } else { + gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2); + } + tcg_temp_free_i32(tmp); + tcg_temp_free_i32(tmp2); + break; default: elementwise: for (pass = 0; pass < (q ? 4 : 2); pass++) {