aboutsummaryrefslogtreecommitdiff
path: root/target-arm/helper-a64.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-03-17 16:31:47 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-03-17 16:31:47 +0000
commita984e42c916ad5afdf3f8660f284857547943aa4 (patch)
treecd3e835f0f03c47c328bb5a4e03a8b082a9306de /target-arm/helper-a64.c
parentd6d60581f3f6778de85ee23427006151b5226667 (diff)
target-arm: A64: Implement PMULL instruction
Implement the PMULL instruction; this is the last unimplemented insn in the three-reg-diff group. Note that PMULL with size 3 is considered part of the AES part of the crypto extensions (see the ID_AA64ISAR0_EL1 register definition in the v8 ARM ARM), so it isn't necessary to burn an extra feature bit on it, even though we're using more feature bits than a single "crypto extension present/not present" toggle. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <rth@twiddle.net> Message-id: 1394822294-14837-2-git-send-email-peter.maydell@linaro.org
Diffstat (limited to 'target-arm/helper-a64.c')
-rw-r--r--target-arm/helper-a64.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/target-arm/helper-a64.c b/target-arm/helper-a64.c
index c2ce33ee88..80ed029053 100644
--- a/target-arm/helper-a64.c
+++ b/target-arm/helper-a64.c
@@ -180,6 +180,36 @@ uint64_t HELPER(simd_tbl)(CPUARMState *env, uint64_t result, uint64_t indices,
return result;
}
+/* Helper function for 64 bit polynomial multiply case:
+ * perform PolynomialMult(op1, op2) and return either the top or
+ * bottom half of the 128 bit result.
+ */
+uint64_t HELPER(neon_pmull_64_lo)(uint64_t op1, uint64_t op2)
+{
+ int bitnum;
+ uint64_t res = 0;
+
+ for (bitnum = 0; bitnum < 64; bitnum++) {
+ if (op1 & (1ULL << bitnum)) {
+ res ^= op2 << bitnum;
+ }
+ }
+ return res;
+}
+uint64_t HELPER(neon_pmull_64_hi)(uint64_t op1, uint64_t op2)
+{
+ int bitnum;
+ uint64_t res = 0;
+
+ /* bit 0 of op1 can't influence the high 64 bits at all */
+ for (bitnum = 1; bitnum < 64; bitnum++) {
+ if (op1 & (1ULL << bitnum)) {
+ res ^= op2 >> (64 - bitnum);
+ }
+ }
+ return res;
+}
+
/* 64bit/double versions of the neon float compare functions */
uint64_t HELPER(neon_ceq_f64)(float64 a, float64 b, void *fpstp)
{