From: Jacob Lifshay Date: Tue, 15 Mar 2022 04:56:03 +0000 (-0700) Subject: add WIP cldivrem -- see if [[!inline ...]] works X-Git-Tag: opf_rfc_ls005_v1~3060 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4c1d16153f318c1fbf17c3f050ba5f7f64ff5bbe;p=libreriscv.git add WIP cldivrem -- see if [[!inline ...]] works --- diff --git a/openpower/sv/bitmanip.mdwn b/openpower/sv/bitmanip.mdwn index 3923c0bef..bf65a028a 100644 --- a/openpower/sv/bitmanip.mdwn +++ b/openpower/sv/bitmanip.mdwn @@ -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 index 000000000..5bf49b120 --- /dev/null +++ b/openpower/sv/bitmanip_inlines/cldivrem.py @@ -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