sc_nbfriends.inc revision 12854
12SN/A/*****************************************************************************
21762SN/A
32SN/A  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
42SN/A  more contributor license agreements.  See the NOTICE file distributed
52SN/A  with this work for additional information regarding copyright ownership.
62SN/A  Accellera licenses this file to you under the Apache License, Version 2.0
72SN/A  (the "License"); you may not use this file except in compliance with the
82SN/A  License.  You may obtain a copy of the License at
92SN/A
102SN/A    http://www.apache.org/licenses/LICENSE-2.0
112SN/A
122SN/A  Unless required by applicable law or agreed to in writing, software
132SN/A  distributed under the License is distributed on an "AS IS" BASIS,
142SN/A  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
152SN/A  implied.  See the License for the specific language governing
162SN/A  permissions and limitations under the License.
172SN/A
182SN/A *****************************************************************************/
192SN/A
202SN/A/*****************************************************************************
212SN/A
222SN/A  sc_nbfriends.inc -- Friend functions for both sc_signed and sc_unsigned
232SN/A                      classes. The vec_* functions are called through either
242SN/A                      these functions or those in sc_nbexterns.cpp. These
252SN/A                      functions perform their work on two inputs u and v, and
262SN/A                      return the result object. The functions in
272665Ssaidi@eecs.umich.edu                      sc_nbexterns.cpp perform their work on one of their
282665Ssaidi@eecs.umich.edu                      inputs.
292665Ssaidi@eecs.umich.edu
302SN/A                      The functions here try to use faster algorithms in case
312SN/A                      the input numbers are small. The bitwise functions (and,
325569Snate@binkert.org                      or, and xor) need the 2's complement representations of
335569Snate@binkert.org                      their inputs. Instead of complementing their inputs
342SN/A                      first and then processing, they complement their inputs
355569Snate@binkert.org                      while processing without allocating extra temporary
363614Sgblack@eecs.umich.edu                      memory.
377678Sgblack@eecs.umich.edu
383614Sgblack@eecs.umich.edu  Original Author: Ali Dasdan, Synopsys, Inc.
393614Sgblack@eecs.umich.edu
402166SN/A *****************************************************************************/
412147SN/A
425569Snate@binkert.org/*****************************************************************************
432167SN/A
442147SN/A  MODIFICATION LOG - modifiers, enter your name, affiliation, date and
452090SN/A  changes you are making here.
462222SN/A
472090SN/A      Name, Affiliation, Date:
482201SN/A  Description of Modification:
492201SN/A
502201SN/A *****************************************************************************/
512112SN/A
522174SN/A
537678Sgblack@eecs.umich.edu// ----------------------------------------------------------------------------
547678Sgblack@eecs.umich.edu//  Naming conventions:
552174SN/A//  For sc_signed or sc_unsigned number u:
562175SN/A//    us : u's sign, unb : u's number of bits,
572222SN/A//    und : u's number of digits, ud : u's digits array.
582SN/A// ----------------------------------------------------------------------------
592SN/A
602203SN/A// ----------------------------------------------------------------------------
612166SN/A//  SECTION: Friend functions for PLUS operators.
622166SN/A// ----------------------------------------------------------------------------
632203SN/A
642166SN/A// Handles cases 3 and 4 and returns the result.
652222SN/ACLASS_TYPE
665569Snate@binkert.orgADD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
672166SN/A           small_type vs, int vnb, int vnd, const sc_digit *vd)
684695Sgblack@eecs.umich.edu{
692166SN/A    und = vec_skip_leading_zeros(und, ud);
702222SN/A    vnd = vec_skip_leading_zeros(vnd, vd);
714695Sgblack@eecs.umich.edu
722166SN/A    int nb = sc_max(unb, vnb);
732166SN/A    int nd = sc_max(und, vnd) + 1;
742203SN/A
752166SN/A#ifdef SC_MAX_NBITS
762166SN/A    test_bound(nb);
772203SN/A    sc_digit d[MAX_NDIGITS];
782166SN/A#else
792222SN/A    sc_digit *d = new sc_digit[nd];
805569Snate@binkert.org#endif
812166SN/A
824695Sgblack@eecs.umich.edu    d[nd - 1] = d[nd - 2] = 0;
832166SN/A
842222SN/A    // case 3
854695Sgblack@eecs.umich.edu    if (us == vs) {
862166SN/A
872166SN/A        ++nb;
882166SN/A
892166SN/A        if ((und == 1) && (vnd == 1)) {
902203SN/A            sc_digit carry = (*ud) + (*vd);
912166SN/A            d[0] = carry & DIGIT_MASK;
922166SN/A            d[1] = carry >> BITS_PER_DIGIT;
932147SN/A        } else if (und >= vnd) {
942090SN/A            vec_add(und, ud, vnd, vd, d);
952147SN/A        } else {
962147SN/A            vec_add(vnd, vd, und, ud, d);
972147SN/A        }
982222SN/A    } else {
995569Snate@binkert.org        // case 4
1002112SN/A        int cmp_res = vec_cmp(und, ud, vnd, vd);
1014695Sgblack@eecs.umich.edu
1022147SN/A        if (cmp_res == 0) { // u == v
1032222SN/A#ifndef SC_MAX_NBITS
1042147SN/A            delete[] d;
1052090SN/A#endif
1062147SN/A            return CLASS_TYPE();
1072090SN/A        }
1082147SN/A
1092147SN/A        if (cmp_res > 0) { // u > v
1102147SN/A            if ((und == 1) && (vnd == 1))
1112222SN/A                d[0] = (*ud) - (*vd);
1125569Snate@binkert.org            else
1135569Snate@binkert.org                vec_sub(und, ud, vnd, vd, d);
1145569Snate@binkert.org        } else { // u < v
1155569Snate@binkert.org            us = -us;
1162112SN/A            if ((und == 1) && (vnd == 1))
1174695Sgblack@eecs.umich.edu                d[0] = (*vd) - (*ud);
1182147SN/A            else
1192222SN/A                vec_sub(vnd, vd, und, ud, d);
1202203SN/A        }
1217678Sgblack@eecs.umich.edu    }
1227678Sgblack@eecs.umich.edu    return CLASS_TYPE(us, nb, nd, d);
1232203SN/A}
1242147SN/A
1252090SN/A
1262147SN/A// ----------------------------------------------------------------------------
1272090SN/A//  SECTION: Friend functions of MULTIPLICATION operators.
1282147SN/A// ----------------------------------------------------------------------------
1292147SN/A
1302147SN/A// Handles the case 4 and returns the result.
1312222SN/ACLASS_TYPE
1325569Snate@binkert.orgMUL_HELPER(small_type s, int unb, int und,  const sc_digit *ud,
1335569Snate@binkert.org           int vnb, int vnd, const sc_digit *vd)
1345569Snate@binkert.org{
1355569Snate@binkert.org    und = vec_skip_leading_zeros(und, ud);
1362112SN/A    vnd = vec_skip_leading_zeros(vnd, vd);
1374695Sgblack@eecs.umich.edu
1382147SN/A    int nb = unb + vnb;
1392222SN/A    int nd = und + vnd;
1402147SN/A
1412090SN/A#ifdef SC_MAX_NBITS
1422502SN/A    test_bound(nb);
1432502SN/A    sc_digit d[MAX_NDIGITS];
1444997Sgblack@eecs.umich.edu#else
1455568Snate@binkert.org    sc_digit *d = new sc_digit[nd];
1465736Snate@binkert.org#endif
1472502SN/A
1485569Snate@binkert.org    vec_zero(nd, d);
1492502SN/A
1505736Snate@binkert.org    sc_digit ud0 = (*ud);
1512502SN/A    sc_digit vd0 = (*vd);
1522502SN/A
1534695Sgblack@eecs.umich.edu    if ((vnd == 1) && (vd0 == 1)) {
1542502SN/A        vec_copy(und, d, ud);
1552502SN/A    } else if ((und == 1) && (ud0 == 1)) {
1562502SN/A        vec_copy(vnd, d, vd);
1577678Sgblack@eecs.umich.edu    } else if ((und == 1) && (vnd == 1) &&
1587678Sgblack@eecs.umich.edu               (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
1592502SN/A        d[0] = ud0 * vd0;
1602502SN/A    } else if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) {
1612502SN/A        vec_mul_small(vnd, vd, ud0, d);
1622502SN/A    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
1632090SN/A        vec_mul_small(und, ud, vd0, d);
1642147SN/A    } else if (vnd < und) {
1652147SN/A        vec_mul(und, ud, vnd, vd, d);
1662147SN/A    } else {
1672222SN/A        vec_mul(vnd, vd, und, ud, d);
1685569Snate@binkert.org    }
1692112SN/A    return CLASS_TYPE(s, nb, nd, d);
1705736Snate@binkert.org}
1712502SN/A
1722502SN/A
1734695Sgblack@eecs.umich.edu// ----------------------------------------------------------------------------
1742147SN/A//  SECTION: Friend functions for DIVISION operators.
1752222SN/A// ----------------------------------------------------------------------------
1764997Sgblack@eecs.umich.edu
1777678Sgblack@eecs.umich.edu// Handles the cases 3-4 and returns the result.
1787678Sgblack@eecs.umich.eduCLASS_TYPE
1794997Sgblack@eecs.umich.eduDIV_HELPER(small_type s, int unb, int und, const sc_digit *ud,
1802147SN/A           int vnb, int vnd, const sc_digit *vd)
1812090SN/A{
1822502SN/A    und = vec_skip_leading_zeros(und, ud);
1832090SN/A    vnd = vec_skip_leading_zeros(vnd, vd);
1842147SN/A
1852147SN/A    int cmp_res = vec_cmp(und, ud, vnd, vd);
1862147SN/A
1872222SN/A    // u < v => u / v = 0 - case 4
1885569Snate@binkert.org    if (cmp_res < 0)
1892112SN/A        return CLASS_TYPE();
1905736Snate@binkert.org
1912502SN/A    // One extra digit for d is allocated to simplify vec_div_*().
1922502SN/A    int nd = sc_max(und, vnd) + 1;
1934695Sgblack@eecs.umich.edu
1942147SN/A#ifdef SC_MAX_NBITS
1952222SN/A    sc_digit d[MAX_NDIGITS + 1];
1962147SN/A#else
1972090SN/A    sc_digit *d = new sc_digit[nd];
1982502SN/A#endif
1992090SN/A
2002147SN/A    vec_zero(nd, d);
2012147SN/A    sc_digit vd0 = (*vd);
2022147SN/A
2032222SN/A    // u = v => u / v = 1 - case 3
2045569Snate@binkert.org    if (cmp_res == 0) {
2052112SN/A        d[0] = 1;
2065736Snate@binkert.org    // else if u > v - case 5
2072502SN/A    } else if ((vnd == 1) && (vd0 == 1)) {
2082502SN/A        vec_copy(und, d, ud);
2094695Sgblack@eecs.umich.edu    } else if ((vnd == 1) && (und == 1)) {
2102147SN/A        d[0] = (*ud) / vd0;
2112222SN/A    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
2122147SN/A        vec_div_small(und, ud, vd0, d);
2132090SN/A    } else {
2142502SN/A        vec_div_large(und, ud, vnd, vd, d);
2152090SN/A    }
2162147SN/A
2172147SN/A    return CLASS_TYPE(s, sc_max(unb, vnb), nd - 1, d);
2182147SN/A}
2192222SN/A
2205569Snate@binkert.org
2212112SN/A// ----------------------------------------------------------------------------
2225736Snate@binkert.org//  SECTION: Friend functions for MOD operators.
2232502SN/A// ----------------------------------------------------------------------------
2242502SN/A
2254695Sgblack@eecs.umich.edu// Handles the cases 3-4 and returns the result.
2262147SN/ACLASS_TYPE
2272222SN/AMOD_HELPER(small_type us, int unb, int und, const sc_digit *ud,
2282147SN/A           int vnb, int vnd, const sc_digit *vd)
2292090SN/A{
2302502SN/A    und = vec_skip_leading_zeros(und, ud);
2312090SN/A    vnd = vec_skip_leading_zeros(vnd, vd);
2322147SN/A
2332147SN/A    int cmp_res = vec_cmp(und, ud, vnd, vd);
2342147SN/A    // u = v => u % v = 0 - case 3
2352222SN/A    if (cmp_res == 0)
2365569Snate@binkert.org        return CLASS_TYPE();
2372112SN/A
2385736Snate@binkert.org    sc_digit vd0 = (*vd);
2392502SN/A    if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))
2402502SN/A        return CLASS_TYPE();
2414695Sgblack@eecs.umich.edu
2422147SN/A    // One extra digit for d is allocated to simplify vec_div_*().
2432222SN/A    int nd = sc_max(und, vnd) + 1;
2442147SN/A
2452090SN/A#ifdef SC_MAX_NBITS
2462502SN/A    sc_digit d[MAX_NDIGITS + 1];
2472502SN/A#else
2484997Sgblack@eecs.umich.edu    sc_digit *d = new sc_digit[nd];
2492502SN/A#endif
2505569Snate@binkert.org
2512502SN/A    vec_zero(nd, d);
2525569Snate@binkert.org
2534695Sgblack@eecs.umich.edu    // u < v => u % v = u - case 4
2542505SN/A    if (cmp_res < 0) {
2552505SN/A        vec_copy(und, d, ud);
2562502SN/A    // else if u > v - case 5
2577678Sgblack@eecs.umich.edu    } else if ((vnd == 1) && (und == 1)) {
2587678Sgblack@eecs.umich.edu        d[0] = (*ud) % vd0;
2592502SN/A    } else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) {
2602502SN/A        d[0] = vec_rem_small(und, ud, vd0);
2612502SN/A    } else {
2622502SN/A        vec_rem_large(und, ud, vnd, vd, d);
2632090SN/A    }
2642147SN/A
2652147SN/A    us = check_for_zero(us, nd - 1, d);
2662147SN/A
2672222SN/A    if (us == SC_ZERO) {
2685569Snate@binkert.org#ifndef SC_MAX_NBITS
2692112SN/A        delete[] d;
2705569Snate@binkert.org#endif
2714695Sgblack@eecs.umich.edu        return CLASS_TYPE();
2722502SN/A    } else {
2732502SN/A        return CLASS_TYPE(us, sc_min(unb, vnb), nd - 1, d);
2744997Sgblack@eecs.umich.edu    }
2757678Sgblack@eecs.umich.edu}
2767678Sgblack@eecs.umich.edu
2774997Sgblack@eecs.umich.edu
2782502SN/A// ----------------------------------------------------------------------------
2792502SN/A//  SECTION: Friend functions for AND operators.
2802502SN/A// ----------------------------------------------------------------------------
2812502SN/A
2822502SN/A// Handles the cases 2-5 and returns the result.
2832502SN/ACLASS_TYPE
2842502SN/AAND_HELPER(small_type us, int unb, int und, const sc_digit *ud,
2852502SN/A           small_type vs, int vnb, int vnd, const sc_digit *vd)
2865569Snate@binkert.org{
2872502SN/A    int nb = sc_max(unb, vnb);
2885569Snate@binkert.org    int nd = sc_max(und, vnd);
2894695Sgblack@eecs.umich.edu
2902147SN/A#ifdef SC_MAX_NBITS
2912222SN/A    sc_digit dbegin[MAX_NDIGITS];
2922147SN/A#else
2932090SN/A    sc_digit *dbegin = new sc_digit[nd];
2942147SN/A#endif
2952090SN/A
2962147SN/A    sc_digit *d = dbegin;
2972147SN/A
2982147SN/A    const sc_digit *x;
2992222SN/A    const sc_digit *y;
3005569Snate@binkert.org    int xnd;
3012112SN/A    int ynd;
3024695Sgblack@eecs.umich.edu    small_type xs;
3032147SN/A    small_type ys;
3042222SN/A
3052147SN/A    if (und >= vnd) {
3062090SN/A        x = ud;
3072147SN/A        y = vd;
3082090SN/A        xnd = und;
3092147SN/A        ynd = vnd;
3102147SN/A        xs = us;
3112147SN/A        ys = vs;
3122222SN/A    } else {
3135569Snate@binkert.org        y = ud;
3142112SN/A        x = vd;
3154695Sgblack@eecs.umich.edu        ynd = und;
3162147SN/A        xnd = vnd;
3172222SN/A        ys = us;
3182147SN/A        xs = vs;
3192090SN/A    }
3202147SN/A
3212090SN/A    const sc_digit *xend = (x + xnd);
3222147SN/A    const sc_digit *yend = (y + ynd);
3232147SN/A
3242147SN/A    // x is longer than y.
3252222SN/A    small_type s = mul_signs(xs, ys);
3265569Snate@binkert.org    if (s > 0) {
3275569Snate@binkert.org        if (xs > 0) { // case 2
3285569Snate@binkert.org            while (y < yend)
3295569Snate@binkert.org                (*d++) = (*x++) & (*y++);
3302112SN/A            while (x++ < xend)
3314695Sgblack@eecs.umich.edu                (*d++) = 0;
3322147SN/A        } else { // case 3
3332222SN/A            sc_digit xcarry = 1;
3342147SN/A            sc_digit ycarry = 1;
3352090SN/A            while (y < yend) {
3362147SN/A                xcarry += (~(*x++) & DIGIT_MASK);
3372090SN/A                ycarry += (~(*y++) & DIGIT_MASK);
3382147SN/A                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
3392147SN/A                xcarry >>= BITS_PER_DIGIT;
3402147SN/A                ycarry >>= BITS_PER_DIGIT;
3412222SN/A            }
3425569Snate@binkert.org            while (x < xend) {
3432112SN/A                xcarry += (~(*x++) & DIGIT_MASK);
3444695Sgblack@eecs.umich.edu                ycarry += DIGIT_MASK;
3452147SN/A                (*d++) = (xcarry & ycarry) & DIGIT_MASK;
3462222SN/A                xcarry >>= BITS_PER_DIGIT;
3472147SN/A                ycarry >>= BITS_PER_DIGIT;
3482090SN/A            }
3495569Snate@binkert.org        }
3502167SN/A    } else {
3515569Snate@binkert.org        if (xs > 0) { // case 4
352            sc_digit ycarry = 1;
353            while (y < yend) {
354                ycarry += (~(*y++) & DIGIT_MASK);
355                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
356                ycarry >>= BITS_PER_DIGIT;
357            }
358            while (x < xend) {
359                ycarry += DIGIT_MASK;
360                (*d++) = ((*x++) & ycarry) & DIGIT_MASK;
361                ycarry >>= BITS_PER_DIGIT;
362            }
363        } else { // case 5
364            sc_digit xcarry = 1;
365            while (y < yend) {
366                xcarry += (~(*x++) & DIGIT_MASK);
367                (*d++) = (xcarry & (*y++)) & DIGIT_MASK;
368                xcarry >>= BITS_PER_DIGIT;
369            }
370            while (x++ < xend)
371                (*d++) = 0;
372        }
373    }
374    s = convert_signed_2C_to_SM(nb, nd, dbegin);
375    return CLASS_TYPE(s, nb, nd, dbegin);
376}
377
378
379// ----------------------------------------------------------------------------
380//  SECTION: Friend functions for OR operators.
381// ----------------------------------------------------------------------------
382
383// Handles the cases 3-5 and returns the result.
384CLASS_TYPE
385OR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
386          small_type vs, int vnb, int vnd, const sc_digit *vd)
387{
388    int nb = sc_max(unb, vnb);
389    int nd = sc_max(und, vnd);
390
391#ifdef SC_MAX_NBITS
392    sc_digit dbegin[MAX_NDIGITS];
393#else
394    sc_digit *dbegin = new sc_digit[nd];
395#endif
396    sc_digit *d = dbegin;
397    const sc_digit *x;
398    const sc_digit *y;
399    int xnd;
400    int ynd;
401    small_type xs;
402    small_type ys;
403
404    if (und >= vnd) {
405        x = ud;
406        y = vd;
407        xnd = und;
408        ynd = vnd;
409        xs = us;
410        ys = vs;
411    } else {
412        y = ud;
413        x = vd;
414        ynd = und;
415        xnd = vnd;
416        ys = us;
417        xs = vs;
418    }
419
420    const sc_digit *xend = (x + xnd);
421    const sc_digit *yend = (y + ynd);
422
423    // x is longer than y.
424    small_type s = mul_signs(xs, ys);
425    if (s > 0) {
426        if (xs > 0) { // case 3
427            while (y < yend)
428                (*d++) = (*x++) | (*y++);
429            while (x < xend)
430                (*d++) = (*x++);
431        } else { // case 4
432            sc_digit xcarry = 1;
433            sc_digit ycarry = 1;
434            while (y < yend) {
435                xcarry += (~(*x++) & DIGIT_MASK);
436                ycarry += (~(*y++) & DIGIT_MASK);
437                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
438                xcarry >>= BITS_PER_DIGIT;
439                ycarry >>= BITS_PER_DIGIT;
440            }
441            while (x < xend) {
442                xcarry += (~(*x++) & DIGIT_MASK);
443                ycarry += DIGIT_MASK;
444                (*d++) = (xcarry | ycarry) & DIGIT_MASK;
445                xcarry >>= BITS_PER_DIGIT;
446                ycarry >>= BITS_PER_DIGIT;
447            }
448        }
449    } else {
450        if (xs > 0) { // case 5
451            sc_digit ycarry = 1;
452            while (y < yend) {
453                ycarry += (~(*y++) & DIGIT_MASK);
454                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
455                ycarry >>= BITS_PER_DIGIT;
456            }
457            while (x < xend) {
458                ycarry += DIGIT_MASK;
459                (*d++) = ((*x++) | ycarry) & DIGIT_MASK;
460                ycarry >>= BITS_PER_DIGIT;
461            }
462        } else { // case 6
463            sc_digit xcarry = 1;
464            while (y < yend) {
465                xcarry += (~(*x++) & DIGIT_MASK);
466                (*d++) = (xcarry | (*y++)) & DIGIT_MASK;
467                xcarry >>= BITS_PER_DIGIT;
468            }
469            while (x < xend) {
470                xcarry += (~(*x++) & DIGIT_MASK);
471                (*d++) = xcarry & DIGIT_MASK;
472                xcarry >>= BITS_PER_DIGIT;
473            }
474        }
475    }
476    s = convert_signed_2C_to_SM(nb, nd, dbegin);
477    return CLASS_TYPE(s, nb, nd, dbegin);
478}
479
480
481// ----------------------------------------------------------------------------
482//  SECTION: Friend functions for XOR operators.
483// ----------------------------------------------------------------------------
484
485// Handles the cases 3-5 and returns the result.
486CLASS_TYPE
487XOR_HELPER(small_type us, int unb, int und, const sc_digit *ud,
488           small_type vs, int vnb, int vnd, const sc_digit *vd)
489{
490    int nb = sc_max(unb, vnb);
491    int nd = sc_max(und, vnd);
492
493#ifdef SC_MAX_NBITS
494    sc_digit dbegin[MAX_NDIGITS];
495#else
496    sc_digit *dbegin = new sc_digit[nd];
497#endif
498
499    sc_digit *d = dbegin;
500
501    const sc_digit *x;
502    const sc_digit *y;
503    int xnd;
504    int ynd;
505    small_type xs;
506    small_type ys;
507
508    if (und >= vnd) {
509        x = ud;
510        y = vd;
511        xnd = und;
512        ynd = vnd;
513        xs = us;
514        ys = vs;
515    } else {
516        y = ud;
517        x = vd;
518        ynd = und;
519        xnd = vnd;
520        ys = us;
521        xs = vs;
522    }
523
524    const sc_digit *xend = (x + xnd);
525    const sc_digit *yend = (y + ynd);
526
527    // x is longer than y.
528    small_type s = mul_signs(xs, ys);
529    if (s > 0) {
530        if (xs > 0) { // case 3
531            while (y < yend)
532                (*d++) = ((*x++) ^ (*y++)) & DIGIT_MASK;
533            while (x < xend)
534                (*d++) = (*x++);
535        } else { // case 4
536            sc_digit xcarry = 1;
537            sc_digit ycarry = 1;
538            while (y < yend) {
539                xcarry += (~(*x++) & DIGIT_MASK);
540                ycarry += (~(*y++) & DIGIT_MASK);
541                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
542                xcarry >>= BITS_PER_DIGIT;
543                ycarry >>= BITS_PER_DIGIT;
544            }
545            while (x < xend) {
546                xcarry += (~(*x++) & DIGIT_MASK);
547                ycarry += DIGIT_MASK;
548                (*d++) = (xcarry ^ ycarry) & DIGIT_MASK;
549                xcarry >>= BITS_PER_DIGIT;
550                ycarry >>= BITS_PER_DIGIT;
551            }
552        }
553    } else {
554        if (xs > 0) { // case 5
555            sc_digit ycarry = 1;
556            while (y < yend) {
557                ycarry += (~(*y++) & DIGIT_MASK);
558                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
559                ycarry >>= BITS_PER_DIGIT;
560            }
561            while (x < xend) {
562                ycarry += DIGIT_MASK;
563                (*d++) = ((*x++) ^ ycarry) & DIGIT_MASK;
564                ycarry >>= BITS_PER_DIGIT;
565            }
566        } else { // case 6
567            sc_digit xcarry = 1;
568            while (y < yend) {
569                xcarry += (~(*x++) & DIGIT_MASK);
570                (*d++) = (xcarry ^ (*y++)) & DIGIT_MASK;
571                xcarry >>= BITS_PER_DIGIT;
572            }
573            while (x < xend) {
574                xcarry += (~(*x++) & DIGIT_MASK);
575                (*d++) = xcarry & DIGIT_MASK;
576                xcarry >>= BITS_PER_DIGIT;
577            }
578        }
579    }
580    s = convert_signed_2C_to_SM(nb, nd, dbegin);
581    return CLASS_TYPE(s, nb, nd, dbegin);
582}
583