From: Luke Kenneth Casson Leighton Date: Tue, 26 Apr 2022 12:41:35 +0000 (+0100) Subject: start splitting out bigops X-Git-Tag: opf_rfc_ls005_v1~2585 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=152a3a045dcbaa8afbea1f8efdc49144ffbfbd14;p=libreriscv.git start splitting out bigops --- diff --git a/openpower/sv/biginteger/divmnu64.c b/openpower/sv/biginteger/divmnu64.c index e193a59ed..7906ce099 100644 --- a/openpower/sv/biginteger/divmnu64.c +++ b/openpower/sv/biginteger/divmnu64.c @@ -74,6 +74,63 @@ divrem_t divrem_64_by_32(uint64_t n, uint32_t d) } } +bool bigmul(uint32_t qhat, unsigned product[], unsigned vn[], int m, + int n) +{ + long long t, k; + int s, i; + uint32_t carry = 0; + // VL = n + 1 + // sv.madded product.v, vn.v, qhat.s, carry.s + for (int i = 0; i <= n; i++) + { + uint32_t vn_v = i < n ? vn[i] : 0; + uint64_t value = (uint64_t)vn_v * (uint64_t)qhat + carry; + carry = (uint32_t)(value >> 32); + product[i] = (uint32_t)value; + } + return carry != 0; +} + +bool bigadd(unsigned result[], unsigned vn[], unsigned un[], int m, int n, + bool ca) +{ + // VL = n + 1 + // sv.subfe un_j.v, product.v, un_j.v + for (int i = 0; i <= n; i++) + { + uint64_t value = (uint64_t)vn[i] + (uint64_t)un[i] + ca; + ca = value >> 32 != 0; + result[i] = value; + } + return ca; +} + +bool bigsub(unsigned result[], unsigned vn[], unsigned un[], int m, int n, + bool ca) +{ + // VL = n + 1 + // sv.subfe un_j.v, product.v, un_j.v + for (int i = 0; i <= n; i++) + { + uint64_t value = (uint64_t)~vn[i] + (uint64_t)un[i] + ca; + ca = value >> 32 != 0; + result[i] = value; + } + return ca; +} + +bool bigmulsub(unsigned long long qhat, unsigned vn[], unsigned un[], int j, + int m, int n) +{ + // Multiply and subtract. + uint32_t product[n + 1]; + bigmul(qhat, product, vn, m, n); + bool ca = bigsub(un, product, un, m, n, true); + bool need_fixup = !ca; + return need_fixup; +} + /* q[0], r[0], u[0], and v[0] contain the LEAST significant words. (The sequence is in little-endian order). @@ -143,6 +200,7 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], for (j = m - n; j >= 0; j--) { // Main loop. + uint32_t *un_j = &un[j]; // Compute estimate qhat of q[j] from top 2 digits. uint64_t dig2 = ((uint64_t)un[j + n] << 32) | un[j + n - 1]; divrem_t qr = divrem_64_by_32(dig2, vn[n - 1]); @@ -333,7 +391,6 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], product[i] = (uint32_t)value; } bool ca = true; - uint32_t *un_j = &un[j]; // VL = n + 1 // sv.subfe un_j.v, product.v, un_j.v for (int i = 0; i <= n; i++) @@ -351,14 +408,7 @@ int divmnu(unsigned q[], unsigned r[], const unsigned u[], const unsigned v[], if (need_fixup) { // If we subtracted too q[j] = q[j] - 1; // much, add back. - k = 0; - for (i = 0; i < n; i++) - { - t = (unsigned long long)un[i + j] + vn[i] + k; - un[i + j] = t; - k = t >> 32; - } - un[j + n] = un[j + n] + k; + bigadd(un_j, vn, un_j, m, n, 0); } } // End j. // If the caller wants the remainder, unnormalize