From 576f2d470cdf3da7b15348f4f609e4c7a0070499 Mon Sep 17 00:00:00 2001
From: James M Snell <jasnell@gmail.com>
Date: Thu, 20 Aug 2020 13:14:59 -0700
Subject: [PATCH] Implement popcnt and lzcnt for windows arm64

Fixes: https://github.com/ngtcp2/ngtcp2/issues/261
---
 lib/ngtcp2_cc.c      |  8 ++++++++
 lib/ngtcp2_ringbuf.c | 10 ++++++++++
 2 files changed, 18 insertions(+)

diff --git a/lib/ngtcp2_cc.c b/lib/ngtcp2_cc.c
index bf1a17eb..ef2e63a0 100644
--- a/lib/ngtcp2_cc.c
+++ b/lib/ngtcp2_cc.c
@@ -244,6 +244,14 @@ static uint64_t ngtcp2_cbrt(uint64_t n) {
 #if defined(_MSC_VER)
 #  if defined(_M_X64)
   d = (int)__lzcnt64(n);
+#  elif defined(_M_ARM64)
+  {
+    unsigned long index;
+    d = sizeof(uint64_t) * CHAR_BIT;
+    if (_BitScanReverse64(&index, n)) {
+      d = d - 1 - index;
+    }
+  }
 #  else
   if ((n >> 32) != 0) {
     d = __lzcnt((unsigned int)(n >> 32));
diff --git a/lib/ngtcp2_ringbuf.c b/lib/ngtcp2_ringbuf.c
index 3e43af8f..e4deab1f 100644
--- a/lib/ngtcp2_ringbuf.c
+++ b/lib/ngtcp2_ringbuf.c
@@ -31,6 +31,16 @@
 
 #include "ngtcp2_macro.h"
 
+#if defined(_MSC_VER) && defined(_M_ARM64)
+unsigned int __popcnt(unsigned int x) {
+  unsigned int c = 0;
+  for (; x; ++c) {
+    x &= x - 1;
+  }
+  return c;
+}
+#endif
+
 int ngtcp2_ringbuf_init(ngtcp2_ringbuf *rb, size_t nmemb, size_t size,
                         const ngtcp2_mem *mem) {
 #ifdef WIN32
-- 
GitLab