diff options
author | Aurelien Jarno <aurelien@aurel32.net> | 2013-03-31 12:58:30 +0200 |
---|---|---|
committer | Aurelien Jarno <aurelien@aurel32.net> | 2013-04-13 13:51:56 +0200 |
commit | e71827bc0ed50edb31bee6050bc96b3bd1e0c055 (patch) | |
tree | b2dcf9af2e14a42a87e9c09a6a02a0f2cc29f773 /target-i386/ops_sse.h | |
parent | 8dbd3fc37593c81a04a62cb4266ba9127de4498a (diff) |
target-i386: add pclmulqdq instruction
Reviewed-by: Richard Henderson <rth@twiddle.net>
Reviewed-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Diffstat (limited to 'target-i386/ops_sse.h')
-rw-r--r-- | target-i386/ops_sse.h | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h index a11dba1566..2ee5b8d9dd 100644 --- a/target-i386/ops_sse.h +++ b/target-i386/ops_sse.h @@ -2179,6 +2179,30 @@ target_ulong helper_popcnt(CPUX86State *env, target_ulong n, uint32_t type) return POPCOUNT(n, 5); #endif } + +void glue(helper_pclmulqdq, SUFFIX)(CPUX86State *env, Reg *d, Reg *s, + uint32_t ctrl) +{ + uint64_t ah, al, b, resh, resl; + + ah = 0; + al = d->Q((ctrl & 1) != 0); + b = s->Q((ctrl & 16) != 0); + resh = resl = 0; + + while (b) { + if (b & 1) { + resl ^= al; + resh ^= ah; + } + ah = (ah << 1) | (al >> 63); + al <<= 1; + b >>= 1; + } + + d->Q(0) = resl; + d->Q(1) = resh; +} #endif #undef SHIFT |