add experimental MUL_RSUB_CARRY1 variant
authorLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 18 Apr 2022 19:12:47 +0000 (20:12 +0100)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Mon, 18 Apr 2022 19:12:47 +0000 (20:12 +0100)
openpower/sv/bitmanip/divmnu64.c

index e5cd1f1d15adbcd3c7d21a32d825d3af7dec1ad9..52f1715aa7ac42a50f1341a0d9bd1f799bb9154b 100644 (file)
@@ -107,7 +107,7 @@ again:
         if (rhat < b) goto again;
       }
 
-#define MUL_RSUB_CARRY
+#define MUL_RSUB_CARRY1
 #ifdef ORIGINAL
       // Multiply and subtract.
       k = 0;
@@ -167,6 +167,33 @@ again:
          un[i + j] = (uint32_t)result;
       }
       bool need_fixup = carry != 1;
+#elif defined(MUL_RSUB_CARRY1)
+      (void)p; // shut up unused variable warning
+
+      // Multiply and subtract.
+      uint32_t carry = 1;
+      uint32_t phi[2000]; // plenty space
+      uint32_t plo[2000]; // plenty space
+      // same mul-and-sub as SUB_MUL_BORROW but not the same
+      // mul-and-sub-minus-one as MUL_RSUB_CARRY
+      for(int i = 0; i <= n; i++) {
+         uint32_t vn_i = i < n ? vn[i] : 0;
+         uint64_t value = un[i + j] - ((uint64_t)qhat * vn_i);
+         plo[i] = value & 0xffffffffLL;
+         phi[i] = value >> 32;
+      }
+      // compensate for the +1 that was added by mul-and-sub by subtracting
+      // it here (as ~(0))
+      for(int i = 0; i <= n; i++) {
+         uint64_t result = (((uint64_t)phi[i]<<32) | plo[i]) + carry+
+                           ~(0); // a way to express "-1"
+         uint32_t result_high = result >> 32;
+         if(carry <= 1)
+            result_high++;
+         carry = result_high;
+         un[i + j] = (uint32_t)result;
+      }
+      bool need_fixup = carry != 1;
 #else
 #error need to define one of ORIGINAL, SUB_MUL_BORROW, or MUL_RSUB_CARRY
 #endif