| /***************************************************************************** | |
| 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 |