summaryrefslogtreecommitdiff
path: root/src/systemc/dt/int/sc_nbexterns.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/systemc/dt/int/sc_nbexterns.cc')
-rw-r--r--src/systemc/dt/int/sc_nbexterns.cc739
1 files changed, 739 insertions, 0 deletions
diff --git a/src/systemc/dt/int/sc_nbexterns.cc b/src/systemc/dt/int/sc_nbexterns.cc
new file mode 100644
index 000000000..479e68e85
--- /dev/null
+++ b/src/systemc/dt/int/sc_nbexterns.cc
@@ -0,0 +1,739 @@
+/*****************************************************************************
+
+ Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
+ more contributor license agreements. See the NOTICE file distributed
+ with this work for additional information regarding copyright ownership.
+ Accellera licenses this file to you under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with the
+ License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied. See the License for the specific language governing
+ permissions and limitations under the License.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ sc_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned
+ classes. These functions work on two parameters u and
+ v, and copy the result to the first parameter u. This
+ is also the reason that they are suffixed with _on_help.
+
+ Original Author: Ali Dasdan, Synopsys, Inc.
+
+ *****************************************************************************/
+
+/*****************************************************************************
+
+ MODIFICATION LOG - modifiers, enter your name, affiliation, date and
+ changes you are making here.
+
+ Name, Affiliation, Date:
+ Description of Modification:
+
+ *****************************************************************************/
+
+
+// $Log: sc_nbexterns.cpp,v $
+// Revision 1.2 2011/02/18 20:19:15 acg
+// Andy Goodrich: updating Copyright notice.
+//
+// Revision 1.1.1.1 2006/12/15 20:20:05 acg
+// SystemC 2.3
+//
+// Revision 1.3 2006/01/13 18:49:32 acg
+// Added $Log command so that CVS check in comments are reproduced in the
+// source.
+//
+
+#include "systemc/ext/dt/int/sc_nbexterns.hh"
+#include "systemc/ext/utils/functions.hh"
+
+namespace sc_dt
+{
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for PLUS operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3 and 4 and returns the result in u.
+void
+add_on_help(small_type &us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ if (us == vs) { // case 3
+ if (und >= vnd)
+ vec_add_on(und, ud, vnd, vd);
+ else
+ vec_add_on2(und, ud, vnd, vd);
+
+ } else { // case 4
+ // vec_cmp expects that und is the number of non-zero digits in ud.
+ int new_und = vec_skip_leading_zeros(und, ud);
+ int cmp_res = vec_cmp(new_und, ud, vnd, vd);
+
+ if (cmp_res == 0) { // u == v
+ us = SC_ZERO;
+ vec_zero(und, ud);
+ return;
+ }
+
+ if (cmp_res > 0) { // u > v
+ vec_sub_on(und, ud, vnd, vd);
+ } else { // u < v
+ us = -us;
+ vec_sub_on2(und, ud, vnd, vd);
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+
+/*
+
+mul_on_help_signed and mul_on_help_unsigned have the same body except
+that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and
+unsigned, respectively. This comment also applies to the
+signed/unsigned versions of div_on_help and mod_on_help. It is
+possible to take COPY_DIGITS out of these functions and create a
+single version of each of these helper functions; however, this will
+impose an onverhead on performance. In the versions below, any change
+in the signed version of a helper function must be carried to a
+corresponding change in the unsigned verion of the same function or
+vice versa.
+
+*/
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions of MULTIPLICATION operators.
+// ----------------------------------------------------------------------------
+
+void
+mul_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_signed
+ { // Body of mul_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ sc_digit ud0 = (*ud);
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ if ((und == 1) && (ud0 == 1)) {
+ COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
+ return;
+ }
+
+ if ((und == 1) && (vnd == 1) &&
+ (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
+
+ sc_digit d = ud0 * vd0;
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
+ return;
+ }
+
+ int nd = und + vnd;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
+ vec_mul_small(vnd, vd, ud0, d);
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_mul_small(und, ud, vd0, d);
+ else if (vnd < und)
+ vec_mul(und, ud, vnd, vd, d);
+ else
+ vec_mul(vnd, vd, und, ud, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+void
+mul_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of mul_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ sc_digit ud0 = (*ud);
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ if ((und == 1) && (ud0 == 1)) {
+ COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
+ return;
+ }
+
+ if ((und == 1) && (vnd == 1) &&
+ (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
+
+ sc_digit d = ud0 * vd0;
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
+ return;
+ }
+
+ int nd = und + vnd;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
+ vec_mul_small(vnd, vd, ud0, d);
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_mul_small(und, ud, vd0, d);
+ else if (vnd < und)
+ vec_mul(und, ud, vnd, vd, d);
+ else
+ vec_mul(vnd, vd, und, ud, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for DIVISION operators.
+// ----------------------------------------------------------------------------
+
+void
+div_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_signed
+ { // Body of div_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ if (cmp_res < 0) { // u < v => u / v = 0 - case 4
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ sc_digit vd0 = (*vd);
+
+ if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ // u = v => u / v = 1 - case 3
+ if (cmp_res == 0)
+ d[0] = 1;
+ else if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) / vd0;
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_div_small(und, ud, vd0, d);
+ else
+ vec_div_large(und, ud, vnd, vd, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+void
+div_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int vnb, int vnd, const sc_digit *vd)
+{
+#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of div_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ if (cmp_res < 0) { // u < v => u / v = 0 - case 4
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ sc_digit vd0 = (*vd);
+
+ if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) {
+ us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ // u = v => u / v = 1 - case 3
+ if (cmp_res == 0)
+ d[0] = 1;
+ else if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) / vd0;
+ else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ vec_div_small(und, ud, vd0, d);
+ else
+ vec_div_large(und, ud, vnd, vd, d);
+
+ COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+#undef CONVERT_SM_to_2C_to_SM
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for MOD operators.
+// ----------------------------------------------------------------------------
+
+void
+mod_on_help_signed(small_type &us, int unb, int und, sc_digit *ud,
+ int /* vnb */, int vnd, const sc_digit *vd)
+{
+#define COPY_DIGITS copy_digits_signed
+ { // Body of mod_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ // u < v => u % v = u - case 4
+ if (cmp_res < 0)
+ return;
+
+ // u = v => u % v = 0 - case 3
+ if (cmp_res == 0) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+ // else if u > v - case 5
+
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) % vd0;
+ if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ d[0] = vec_rem_small(und, ud, vd0);
+ else
+ vec_rem_large(und, ud, vnd, vd, d);
+
+ us = check_for_zero(us, nd - 1, d);
+
+ if (us == SC_ZERO)
+ vec_zero(old_und, ud);
+ else
+ COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+}
+
+
+void
+mod_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud,
+ int /* vnb */, int vnd, const sc_digit *vd)
+{
+#define COPY_DIGITS copy_digits_unsigned
+ { // Body of mod_on_help
+ int old_und = und;
+
+ und = vec_skip_leading_zeros(und, ud);
+ vnd = vec_skip_leading_zeros(vnd, vd);
+
+ int cmp_res = vec_cmp(und, ud, vnd, vd);
+
+ // u < v => u % v = u - case 4
+ if (cmp_res < 0)
+ return;
+
+ // u = v => u % v = 0 - case 3
+ if (cmp_res == 0) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // else if u > v - case 5
+
+ sc_digit vd0 = (*vd);
+
+ if ((vnd == 1) && (vd0 == 1)) {
+ us = SC_ZERO;
+ vec_zero(old_und, ud);
+ return;
+ }
+
+ // One extra digit for d is allocated to simplify vec_div_*().
+ int nd = sc_max(und, vnd) + 1;
+
+#ifdef SC_MAX_NBITS
+ sc_digit d[MAX_NDIGITS + 1];
+#else
+ sc_digit *d = new sc_digit[nd];
+#endif
+
+ vec_zero(nd, d);
+
+ if ((vnd == 1) && (und == 1))
+ d[0] = (*ud) % vd0;
+ if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
+ d[0] = vec_rem_small(und, ud, vd0);
+ else
+ vec_rem_large(und, ud, vnd, vd, d);
+
+ us = check_for_zero(us, nd - 1, d);
+
+ if (us == SC_ZERO)
+ vec_zero(old_und, ud);
+ else
+ COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
+
+#ifndef SC_MAX_NBITS
+ delete [] d;
+#endif
+ }
+#undef COPY_DIGITS
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for AND operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 2-5 and returns the result in u.
+void
+and_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ // Truncate y.
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 2
+ while (y < yend)
+ (*x++) &= (*y++);
+ while (x < xend)
+ (*x++) = 0;
+ } else { // case 3
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry & ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+
+ }
+ } else {
+ if (us > 0) { // case 4
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) &= ycarry & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x++) &= ycarry & DIGIT_MASK;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 5
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry & (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend)
+ (*x++) = 0;
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for OR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result in u.
+void
+or_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 3
+ while (y < yend)
+ (*x++) |= (*y++);
+ // No change for the rest of x.
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry | ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (us > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x) = ((*x) | ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x) = ((*x) | ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry | (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+}
+
+
+// ----------------------------------------------------------------------------
+// SECTION: External functions for XOR operators.
+// ----------------------------------------------------------------------------
+
+// Handles the cases 3-5 and returns the result in u.
+void
+xor_on_help(small_type us, int /* unb */, int und, sc_digit *ud,
+ small_type vs, int /* vnb */, int vnd, const sc_digit *vd)
+{
+ sc_digit *x = ud;
+ const sc_digit *y = vd;
+ int xnd = und;
+ int ynd = vnd;
+
+ if (xnd < ynd)
+ ynd = xnd;
+
+ const sc_digit *xend = (x + xnd);
+ const sc_digit *yend = (y + ynd);
+
+ // x is longer than y.
+ small_type s = mul_signs(us, vs);
+
+ if (s > 0) {
+ if (us > 0) { // case 3
+ while (y < yend) {
+ (*x) = ((*x) ^ (*y)) & DIGIT_MASK;
+ x++;
+ y++;
+ }
+ // No change for the rest of x.
+ } else { // case 4
+ sc_digit xcarry = 1;
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ ycarry += DIGIT_MASK;
+ (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ }
+ } else {
+ if (us > 0) { // case 5
+ sc_digit ycarry = 1;
+ while (y < yend) {
+ ycarry += (~(*y++) & DIGIT_MASK);
+ (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ ycarry += DIGIT_MASK;
+ (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
+ x++;
+ ycarry >>= BITS_PER_DIGIT;
+ }
+ } else { // case 6
+ sc_digit xcarry = 1;
+ while (y < yend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ while (x < xend) {
+ xcarry += (~(*x) & DIGIT_MASK);
+ (*x++) = xcarry & DIGIT_MASK;
+ xcarry >>= BITS_PER_DIGIT;
+ }
+ }
+ }
+}
+
+} // namespace sc_dt