add WIP cldivrem -- see if [[!inline ...]] works
authorJacob Lifshay <programmerjake@gmail.com>
Tue, 15 Mar 2022 04:56:03 +0000 (21:56 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Tue, 15 Mar 2022 04:56:03 +0000 (21:56 -0700)
openpower/sv/bitmanip.mdwn
openpower/sv/bitmanip_inlines/cldivrem.py [new file with mode: 0644]

index 3923c0bef80af6ff0105bc6c2cedcc0ffac87c3a..bf65a028a32b4ba16568aad3ee843aa7f53e5014 100644 (file)
@@ -627,6 +627,13 @@ temp = clmul((RA), (RB)) ^ (RC)
 (RS) = temp
 ```
 
+## `cldivrem` Carry-less Division and Remainder
+
+`cldivrem` isn't an actual instruction, but is just used in the pseudo-code
+for other instructions.
+
+[[!inline pages="bitmanip_inlines/cldivrem.py" raw="true"]]
+
 ## `cldiv` Carry-less Division
 
 ```
diff --git a/openpower/sv/bitmanip_inlines/cldivrem.py b/openpower/sv/bitmanip_inlines/cldivrem.py
new file mode 100644 (file)
index 0000000..5bf49b1
--- /dev/null
@@ -0,0 +1,34 @@
+def cldivrem(n, d, width):
+    """ Carry-less Division and Remainder.
+        `n` and `d` are integers, `width` is the number of bits needed to hold
+        each input/output.
+        Returns a tuple `q, r` of the quotient and remainder.
+    """
+    assert d != 0, "TODO: decide what happens on division by zero"
+    assert 0 <= n < 1 << width, f"bad n (doesn't fit in {width}-bit uint)"
+    assert 0 <= d < 1 << width, f"bad d (doesn't fit in {width}-bit uint)"
+    r = n
+    q = 0
+    r_shift = 0
+    d_shift = 0
+    msb = 1 << (width - 1)
+    for _ in range(width):
+        if r & msb:
+            if d & msb:
+                r ^= d
+                q |= 1
+            else:
+                d <<= 1
+                d_shift += 1
+        else:
+            if d & msb:
+                r <<= 1
+                q <<= 1
+                r_shift += 1
+            else:
+                r <<= 1
+                r_shift += 1
+                d <<= 1
+                d_shift += 1
+    r >>= r_shift
+    return q, r