summaryrefslogtreecommitdiff
path: root/target-i386/ops_sse.h
diff options
context:
space:
mode:
authorAurelien Jarno <aurelien@aurel32.net>2013-03-31 12:58:30 +0200
committerAurelien Jarno <aurelien@aurel32.net>2013-04-13 13:51:56 +0200
commite71827bc0ed50edb31bee6050bc96b3bd1e0c055 (patch)
treeb2dcf9af2e14a42a87e9c09a6a02a0f2cc29f773 /target-i386/ops_sse.h
parent8dbd3fc37593c81a04a62cb4266ba9127de4498a (diff)
downloadqemu-e71827bc0ed50edb31bee6050bc96b3bd1e0c055.tar.gz
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.h24
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