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