diff --git a/ChangeLog b/ChangeLog
index 3895e4c5..b11202d9 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2010-01-08  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
+
+	Submitted by Doug:
+	patch #7010: Win32 enhanced bitbang_delay
+	* bitbang.c (bitbang_calibrate_delay, bitbang_delay): On Win32,
+	use the high-resolution performance counter rather than the
+	uneducated delay loop guess if it is available on the target
+	hardware.
+
 2010-01-08  Joerg Wunsch <j.gnu@uriah.heep.sax.de>
 
 	Submitted by Gerard:
diff --git a/bitbang.c b/bitbang.c
index b52517eb..c7ba89b1 100644
--- a/bitbang.c
+++ b/bitbang.c
@@ -42,7 +42,9 @@
 
 static int delay_decrement;
 
-#if !defined(WIN32NATIVE)
+#if defined(WIN32NATIVE)
+static int has_perfcount;
+#else
 static volatile int done;
 
 typedef void (*mysighandler_t)(int);
@@ -53,22 +55,46 @@ static void alarmhandler(int signo)
   done = 1;
   signal(SIGALRM, saved_alarmhandler);
 }
-#endif /* !WIN32NATIVE */
+#endif /* WIN32NATIVE */
 
 /*
  * Calibrate the microsecond delay loop below.
  */
 static void bitbang_calibrate_delay(void)
 {
-  /*
-   * Right now, we don't have any Win32 implementation for this, so we
-   * can only run on a preconfigured delay stepping there.  The figure
-   * below should at least be correct within an order of magnitude,
-   * judging from the auto-calibration figures seen on various Unix
-   * systems on comparable hardware.
-   */
 #if defined(WIN32NATIVE)
-  delay_decrement = 100;
+  static LARGE_INTEGER freq;
+
+  /*
+   * If the hardware supports a high-resolution performance counter,
+   * we ultimately prefer that one, as it gives quite accurate delays
+   * on modern high-speed CPUs.
+   */
+  if (QueryPerformanceFrequency(&freq))
+  {
+    has_perfcount = 1;
+    if (verbose >= 2)
+      fprintf(stderr,
+              "%s: Using performance counter for bitbang delays\n",
+              progname);
+  }
+  else
+  {
+    /*
+     * If a high-resolution performance counter is not available, we
+     * don't have any Win32 implementation for setting up the
+     * per-microsecond delay count, so we can only run on a
+     * preconfigured delay stepping there.  The figure below should at
+     * least be correct within an order of magnitude, judging from the
+     * auto-calibration figures seen on various Unix systems on
+     * comparable hardware.
+     */
+    if (verbose >= 2)
+      fprintf(stderr,
+      "%s: Using guessed per-microsecond delay count for bitbang delays\n",
+              progname);
+    delay_decrement = 100;
+  }
 #else  /* !WIN32NATIVE */
   struct itimerval itv;
   volatile int i;
@@ -116,10 +142,27 @@ static void bitbang_calibrate_delay(void)
  */
 void bitbang_delay(int us)
 {
+#if defined(WIN32NATIVE)
+  LARGE_INTEGER countNow, countEnd;
+
+  if (has_perfcount)
+  {
+    QueryPerformanceCounter(&countNow);
+    countEnd.QuadPart = countNow.QuadPart + freq.QuadPart * us / 1000000ll;
+
+    while (countNow.QuadPart < countEnd.QuadPart)
+      QueryPerformanceCounter(&countNow);
+  }
+  else /* no performance counters -- run normal uncalibrated delay */
+  {
+#endif  /* WIN32NATIVE */
   volatile int del = us * delay_decrement;
 
   while (del > 0)
     del--;
+#if defined(WIN32NATIVE)
+  }
+#endif /* WIN32NATIVE */
 }
 
 /*