sc_nbexterns.cc revision 12854:c95c35407325
114039Sstacze01@arm.com/***************************************************************************** 214039Sstacze01@arm.com 314039Sstacze01@arm.com Licensed to Accellera Systems Initiative Inc. (Accellera) under one or 414039Sstacze01@arm.com more contributor license agreements. See the NOTICE file distributed 514039Sstacze01@arm.com with this work for additional information regarding copyright ownership. 614039Sstacze01@arm.com Accellera licenses this file to you under the Apache License, Version 2.0 714039Sstacze01@arm.com (the "License"); you may not use this file except in compliance with the 814039Sstacze01@arm.com License. You may obtain a copy of the License at 914039Sstacze01@arm.com 1014039Sstacze01@arm.com http://www.apache.org/licenses/LICENSE-2.0 1114039Sstacze01@arm.com 1214039Sstacze01@arm.com Unless required by applicable law or agreed to in writing, software 1314039Sstacze01@arm.com distributed under the License is distributed on an "AS IS" BASIS, 1414039Sstacze01@arm.com WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 1514039Sstacze01@arm.com implied. See the License for the specific language governing 1614039Sstacze01@arm.com permissions and limitations under the License. 1714039Sstacze01@arm.com 1814039Sstacze01@arm.com *****************************************************************************/ 1914039Sstacze01@arm.com 2014039Sstacze01@arm.com/***************************************************************************** 2114039Sstacze01@arm.com 2214039Sstacze01@arm.com sc_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned 2314039Sstacze01@arm.com classes. These functions work on two parameters u and 2414039Sstacze01@arm.com v, and copy the result to the first parameter u. This 2514039Sstacze01@arm.com is also the reason that they are suffixed with _on_help. 2614039Sstacze01@arm.com 2714039Sstacze01@arm.com Original Author: Ali Dasdan, Synopsys, Inc. 2814039Sstacze01@arm.com 2914039Sstacze01@arm.com *****************************************************************************/ 3014039Sstacze01@arm.com 3114039Sstacze01@arm.com/***************************************************************************** 3214039Sstacze01@arm.com 3314039Sstacze01@arm.com MODIFICATION LOG - modifiers, enter your name, affiliation, date and 3414039Sstacze01@arm.com changes you are making here. 3514039Sstacze01@arm.com 3614039Sstacze01@arm.com Name, Affiliation, Date: 3714039Sstacze01@arm.com Description of Modification: 3814039Sstacze01@arm.com 3914039Sstacze01@arm.com *****************************************************************************/ 4014039Sstacze01@arm.com 4114039Sstacze01@arm.com 4214039Sstacze01@arm.com// $Log: sc_nbexterns.cpp,v $ 4314039Sstacze01@arm.com// Revision 1.2 2011/02/18 20:19:15 acg 4414039Sstacze01@arm.com// Andy Goodrich: updating Copyright notice. 4514039Sstacze01@arm.com// 4614039Sstacze01@arm.com// Revision 1.1.1.1 2006/12/15 20:20:05 acg 4714039Sstacze01@arm.com// SystemC 2.3 4814039Sstacze01@arm.com// 4914039Sstacze01@arm.com// Revision 1.3 2006/01/13 18:49:32 acg 5014039Sstacze01@arm.com// Added $Log command so that CVS check in comments are reproduced in the 5114039Sstacze01@arm.com// source. 5214039Sstacze01@arm.com// 5314039Sstacze01@arm.com 5414039Sstacze01@arm.com#include "systemc/ext/dt/int/sc_nbexterns.hh" 5514039Sstacze01@arm.com#include "systemc/ext/utils/functions.hh" 5614039Sstacze01@arm.com 5714039Sstacze01@arm.comnamespace sc_dt 5814039Sstacze01@arm.com{ 5914104Sgiacomo.travaglini@arm.com 6014104Sgiacomo.travaglini@arm.com// ---------------------------------------------------------------------------- 6114104Sgiacomo.travaglini@arm.com// SECTION: External functions for PLUS operators. 6214104Sgiacomo.travaglini@arm.com// ---------------------------------------------------------------------------- 6314104Sgiacomo.travaglini@arm.com 6414039Sstacze01@arm.com// Handles the cases 3 and 4 and returns the result in u. 6514104Sgiacomo.travaglini@arm.comvoid 6614104Sgiacomo.travaglini@arm.comadd_on_help(small_type &us, int /* unb */, int und, sc_digit *ud, 6714104Sgiacomo.travaglini@arm.com small_type vs, int /* vnb */, int vnd, const sc_digit *vd) 6814104Sgiacomo.travaglini@arm.com{ 6914104Sgiacomo.travaglini@arm.com vnd = vec_skip_leading_zeros(vnd, vd); 7014104Sgiacomo.travaglini@arm.com 7114039Sstacze01@arm.com if (us == vs) { // case 3 7214039Sstacze01@arm.com if (und >= vnd) 7314104Sgiacomo.travaglini@arm.com vec_add_on(und, ud, vnd, vd); 7414039Sstacze01@arm.com else 7514104Sgiacomo.travaglini@arm.com vec_add_on2(und, ud, vnd, vd); 7614039Sstacze01@arm.com 7714039Sstacze01@arm.com } else { // case 4 7814104Sgiacomo.travaglini@arm.com // vec_cmp expects that und is the number of non-zero digits in ud. 7914039Sstacze01@arm.com int new_und = vec_skip_leading_zeros(und, ud); 8014104Sgiacomo.travaglini@arm.com int cmp_res = vec_cmp(new_und, ud, vnd, vd); 8114039Sstacze01@arm.com 8214039Sstacze01@arm.com if (cmp_res == 0) { // u == v 8314039Sstacze01@arm.com us = SC_ZERO; 8414039Sstacze01@arm.com vec_zero(und, ud); 8514064Sadrian.herrera@arm.com return; 8614064Sadrian.herrera@arm.com } 8714039Sstacze01@arm.com 8814039Sstacze01@arm.com if (cmp_res > 0) { // u > v 8914039Sstacze01@arm.com vec_sub_on(und, ud, vnd, vd); 9014039Sstacze01@arm.com } else { // u < v 91 us = -us; 92 vec_sub_on2(und, ud, vnd, vd); 93 } 94 } 95} 96 97 98// ---------------------------------------------------------------------------- 99 100/* 101 102mul_on_help_signed and mul_on_help_unsigned have the same body except 103that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and 104unsigned, respectively. This comment also applies to the 105signed/unsigned versions of div_on_help and mod_on_help. It is 106possible to take COPY_DIGITS out of these functions and create a 107single version of each of these helper functions; however, this will 108impose an onverhead on performance. In the versions below, any change 109in the signed version of a helper function must be carried to a 110corresponding change in the unsigned verion of the same function or 111vice versa. 112 113*/ 114 115 116// ---------------------------------------------------------------------------- 117// SECTION: External functions of MULTIPLICATION operators. 118// ---------------------------------------------------------------------------- 119 120void 121mul_on_help_signed(small_type &us, int unb, int und, sc_digit *ud, 122 int vnb, int vnd, const sc_digit *vd) 123{ 124#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM 125#define COPY_DIGITS copy_digits_signed 126 { // Body of mul_on_help 127 int old_und = und; 128 129 und = vec_skip_leading_zeros(und, ud); 130 vnd = vec_skip_leading_zeros(vnd, vd); 131 132 sc_digit ud0 = (*ud); 133 sc_digit vd0 = (*vd); 134 135 if ((vnd == 1) && (vd0 == 1)) { 136 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); 137 return; 138 } 139 140 if ((und == 1) && (ud0 == 1)) { 141 COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd); 142 return; 143 } 144 145 if ((und == 1) && (vnd == 1) && 146 (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) { 147 148 sc_digit d = ud0 * vd0; 149 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d); 150 return; 151 } 152 153 int nd = und + vnd; 154 155#ifdef SC_MAX_NBITS 156 sc_digit d[MAX_NDIGITS]; 157#else 158 sc_digit *d = new sc_digit[nd]; 159#endif 160 161 vec_zero(nd, d); 162 163 if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) 164 vec_mul_small(vnd, vd, ud0, d); 165 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 166 vec_mul_small(und, ud, vd0, d); 167 else if (vnd < und) 168 vec_mul(und, ud, vnd, vd, d); 169 else 170 vec_mul(vnd, vd, und, ud, d); 171 172 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d); 173 174#ifndef SC_MAX_NBITS 175 delete [] d; 176#endif 177 } 178#undef COPY_DIGITS 179#undef CONVERT_SM_to_2C_to_SM 180} 181 182 183void 184mul_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud, 185 int vnb, int vnd, const sc_digit *vd) 186{ 187#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM 188#define COPY_DIGITS copy_digits_unsigned 189 { // Body of mul_on_help 190 int old_und = und; 191 192 und = vec_skip_leading_zeros(und, ud); 193 vnd = vec_skip_leading_zeros(vnd, vd); 194 195 sc_digit ud0 = (*ud); 196 sc_digit vd0 = (*vd); 197 198 if ((vnd == 1) && (vd0 == 1)) { 199 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); 200 return; 201 } 202 203 if ((und == 1) && (ud0 == 1)) { 204 COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd); 205 return; 206 } 207 208 if ((und == 1) && (vnd == 1) && 209 (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) { 210 211 sc_digit d = ud0 * vd0; 212 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d); 213 return; 214 } 215 216 int nd = und + vnd; 217 218#ifdef SC_MAX_NBITS 219 sc_digit d[MAX_NDIGITS]; 220#else 221 sc_digit *d = new sc_digit[nd]; 222#endif 223 224 vec_zero(nd, d); 225 226 if ((und == 1) && (ud0 < HALF_DIGIT_RADIX)) 227 vec_mul_small(vnd, vd, ud0, d); 228 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 229 vec_mul_small(und, ud, vd0, d); 230 else if (vnd < und) 231 vec_mul(und, ud, vnd, vd, d); 232 else 233 vec_mul(vnd, vd, und, ud, d); 234 235 COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d); 236 237#ifndef SC_MAX_NBITS 238 delete [] d; 239#endif 240 } 241#undef COPY_DIGITS 242#undef CONVERT_SM_to_2C_to_SM 243} 244 245 246// ---------------------------------------------------------------------------- 247// SECTION: External functions for DIVISION operators. 248// ---------------------------------------------------------------------------- 249 250void 251div_on_help_signed(small_type &us, int unb, int und, sc_digit *ud, 252 int vnb, int vnd, const sc_digit *vd) 253{ 254#define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM 255#define COPY_DIGITS copy_digits_signed 256 { // Body of div_on_help 257 int old_und = und; 258 259 und = vec_skip_leading_zeros(und, ud); 260 vnd = vec_skip_leading_zeros(vnd, vd); 261 262 int cmp_res = vec_cmp(und, ud, vnd, vd); 263 264 if (cmp_res < 0) { // u < v => u / v = 0 - case 4 265 us = SC_ZERO; 266 vec_zero(old_und, ud); 267 return; 268 } 269 270 sc_digit vd0 = (*vd); 271 272 if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) { 273 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); 274 return; 275 } 276 277 // One extra digit for d is allocated to simplify vec_div_*(). 278 int nd = sc_max(und, vnd) + 1; 279 280#ifdef SC_MAX_NBITS 281 sc_digit d[MAX_NDIGITS + 1]; 282#else 283 sc_digit *d = new sc_digit[nd]; 284#endif 285 286 vec_zero(nd, d); 287 288 // u = v => u / v = 1 - case 3 289 if (cmp_res == 0) 290 d[0] = 1; 291 else if ((vnd == 1) && (und == 1)) 292 d[0] = (*ud) / vd0; 293 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 294 vec_div_small(und, ud, vd0, d); 295 else 296 vec_div_large(und, ud, vnd, vd, d); 297 298 COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d); 299 300#ifndef SC_MAX_NBITS 301 delete [] d; 302#endif 303 } 304#undef COPY_DIGITS 305#undef CONVERT_SM_to_2C_to_SM 306} 307 308 309void 310div_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud, 311 int vnb, int vnd, const sc_digit *vd) 312{ 313#define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM 314#define COPY_DIGITS copy_digits_unsigned 315 { // Body of div_on_help 316 int old_und = und; 317 318 und = vec_skip_leading_zeros(und, ud); 319 vnd = vec_skip_leading_zeros(vnd, vd); 320 321 int cmp_res = vec_cmp(und, ud, vnd, vd); 322 323 if (cmp_res < 0) { // u < v => u / v = 0 - case 4 324 us = SC_ZERO; 325 vec_zero(old_und, ud); 326 return; 327 } 328 329 sc_digit vd0 = (*vd); 330 331 if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1)) { 332 us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud); 333 return; 334 } 335 336 // One extra digit for d is allocated to simplify vec_div_*(). 337 int nd = sc_max(und, vnd) + 1; 338 339#ifdef SC_MAX_NBITS 340 sc_digit d[MAX_NDIGITS + 1]; 341#else 342 sc_digit *d = new sc_digit[nd]; 343#endif 344 345 vec_zero(nd, d); 346 347 // u = v => u / v = 1 - case 3 348 if (cmp_res == 0) 349 d[0] = 1; 350 else if ((vnd == 1) && (und == 1)) 351 d[0] = (*ud) / vd0; 352 else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 353 vec_div_small(und, ud, vd0, d); 354 else 355 vec_div_large(und, ud, vnd, vd, d); 356 357 COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d); 358 359#ifndef SC_MAX_NBITS 360 delete [] d; 361#endif 362 } 363#undef COPY_DIGITS 364#undef CONVERT_SM_to_2C_to_SM 365} 366 367 368// ---------------------------------------------------------------------------- 369// SECTION: External functions for MOD operators. 370// ---------------------------------------------------------------------------- 371 372void 373mod_on_help_signed(small_type &us, int unb, int und, sc_digit *ud, 374 int /* vnb */, int vnd, const sc_digit *vd) 375{ 376#define COPY_DIGITS copy_digits_signed 377 { // Body of mod_on_help 378 int old_und = und; 379 380 und = vec_skip_leading_zeros(und, ud); 381 vnd = vec_skip_leading_zeros(vnd, vd); 382 383 int cmp_res = vec_cmp(und, ud, vnd, vd); 384 385 // u < v => u % v = u - case 4 386 if (cmp_res < 0) 387 return; 388 389 // u = v => u % v = 0 - case 3 390 if (cmp_res == 0) { 391 us = SC_ZERO; 392 vec_zero(old_und, ud); 393 return; 394 } 395 // else if u > v - case 5 396 397 sc_digit vd0 = (*vd); 398 399 if ((vnd == 1) && (vd0 == 1)) { 400 us = SC_ZERO; 401 vec_zero(old_und, ud); 402 return; 403 } 404 405 // One extra digit for d is allocated to simplify vec_div_*(). 406 int nd = sc_max(und, vnd) + 1; 407 408#ifdef SC_MAX_NBITS 409 sc_digit d[MAX_NDIGITS + 1]; 410#else 411 sc_digit *d = new sc_digit[nd]; 412#endif 413 414 vec_zero(nd, d); 415 416 if ((vnd == 1) && (und == 1)) 417 d[0] = (*ud) % vd0; 418 if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 419 d[0] = vec_rem_small(und, ud, vd0); 420 else 421 vec_rem_large(und, ud, vnd, vd, d); 422 423 us = check_for_zero(us, nd - 1, d); 424 425 if (us == SC_ZERO) 426 vec_zero(old_und, ud); 427 else 428 COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d); 429 430#ifndef SC_MAX_NBITS 431 delete [] d; 432#endif 433 } 434#undef COPY_DIGITS 435} 436 437 438void 439mod_on_help_unsigned(small_type &us, int unb, int und, sc_digit *ud, 440 int /* vnb */, int vnd, const sc_digit *vd) 441{ 442#define COPY_DIGITS copy_digits_unsigned 443 { // Body of mod_on_help 444 int old_und = und; 445 446 und = vec_skip_leading_zeros(und, ud); 447 vnd = vec_skip_leading_zeros(vnd, vd); 448 449 int cmp_res = vec_cmp(und, ud, vnd, vd); 450 451 // u < v => u % v = u - case 4 452 if (cmp_res < 0) 453 return; 454 455 // u = v => u % v = 0 - case 3 456 if (cmp_res == 0) { 457 us = SC_ZERO; 458 vec_zero(old_und, ud); 459 return; 460 } 461 462 // else if u > v - case 5 463 464 sc_digit vd0 = (*vd); 465 466 if ((vnd == 1) && (vd0 == 1)) { 467 us = SC_ZERO; 468 vec_zero(old_und, ud); 469 return; 470 } 471 472 // One extra digit for d is allocated to simplify vec_div_*(). 473 int nd = sc_max(und, vnd) + 1; 474 475#ifdef SC_MAX_NBITS 476 sc_digit d[MAX_NDIGITS + 1]; 477#else 478 sc_digit *d = new sc_digit[nd]; 479#endif 480 481 vec_zero(nd, d); 482 483 if ((vnd == 1) && (und == 1)) 484 d[0] = (*ud) % vd0; 485 if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX)) 486 d[0] = vec_rem_small(und, ud, vd0); 487 else 488 vec_rem_large(und, ud, vnd, vd, d); 489 490 us = check_for_zero(us, nd - 1, d); 491 492 if (us == SC_ZERO) 493 vec_zero(old_und, ud); 494 else 495 COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d); 496 497#ifndef SC_MAX_NBITS 498 delete [] d; 499#endif 500 } 501#undef COPY_DIGITS 502} 503 504 505// ---------------------------------------------------------------------------- 506// SECTION: External functions for AND operators. 507// ---------------------------------------------------------------------------- 508 509// Handles the cases 2-5 and returns the result in u. 510void 511and_on_help(small_type us, int /* unb */, int und, sc_digit *ud, 512 small_type vs, int /* vnb */, int vnd, const sc_digit *vd) 513{ 514 sc_digit *x = ud; 515 const sc_digit *y = vd; 516 int xnd = und; 517 int ynd = vnd; 518 519 // Truncate y. 520 if (xnd < ynd) 521 ynd = xnd; 522 523 const sc_digit *xend = (x + xnd); 524 const sc_digit *yend = (y + ynd); 525 526 // x is longer than y. 527 small_type s = mul_signs(us, vs); 528 529 if (s > 0) { 530 if (us > 0) { // case 2 531 while (y < yend) 532 (*x++) &= (*y++); 533 while (x < xend) 534 (*x++) = 0; 535 } else { // case 3 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 (*x++) = (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 (*x++) = (xcarry & ycarry) & DIGIT_MASK; 549 xcarry >>= BITS_PER_DIGIT; 550 ycarry >>= BITS_PER_DIGIT; 551 } 552 553 } 554 } else { 555 if (us > 0) { // case 4 556 sc_digit ycarry = 1; 557 while (y < yend) { 558 ycarry += (~(*y++) & DIGIT_MASK); 559 (*x++) &= ycarry & DIGIT_MASK; 560 ycarry >>= BITS_PER_DIGIT; 561 } 562 while (x < xend) { 563 ycarry += DIGIT_MASK; 564 (*x++) &= ycarry & DIGIT_MASK; 565 ycarry >>= BITS_PER_DIGIT; 566 } 567 } else { // case 5 568 sc_digit xcarry = 1; 569 while (y < yend) { 570 xcarry += (~(*x) & DIGIT_MASK); 571 (*x++) = (xcarry & (*y++)) & DIGIT_MASK; 572 xcarry >>= BITS_PER_DIGIT; 573 } 574 while (x < xend) 575 (*x++) = 0; 576 } 577 } 578} 579 580 581// ---------------------------------------------------------------------------- 582// SECTION: External functions for OR operators. 583// ---------------------------------------------------------------------------- 584 585// Handles the cases 3-5 and returns the result in u. 586void 587or_on_help(small_type us, int /* unb */, int und, sc_digit *ud, 588 small_type vs, int /* vnb */, int vnd, const sc_digit *vd) 589{ 590 sc_digit *x = ud; 591 const sc_digit *y = vd; 592 int xnd = und; 593 int ynd = vnd; 594 595 if (xnd < ynd) 596 ynd = xnd; 597 598 const sc_digit *xend = (x + xnd); 599 const sc_digit *yend = (y + ynd); 600 601 // x is longer than y. 602 small_type s = mul_signs(us, vs); 603 604 if (s > 0) { 605 if (us > 0) { // case 3 606 while (y < yend) 607 (*x++) |= (*y++); 608 // No change for the rest of x. 609 } else { // case 4 610 sc_digit xcarry = 1; 611 sc_digit ycarry = 1; 612 while (y < yend) { 613 xcarry += (~(*x) & DIGIT_MASK); 614 ycarry += (~(*y++) & DIGIT_MASK); 615 (*x++) = (xcarry | ycarry) & DIGIT_MASK; 616 xcarry >>= BITS_PER_DIGIT; 617 ycarry >>= BITS_PER_DIGIT; 618 } 619 while (x < xend) { 620 xcarry += (~(*x) & DIGIT_MASK); 621 ycarry += DIGIT_MASK; 622 (*x++) = (xcarry | ycarry) & DIGIT_MASK; 623 xcarry >>= BITS_PER_DIGIT; 624 ycarry >>= BITS_PER_DIGIT; 625 } 626 } 627 } else { 628 if (us > 0) { // case 5 629 sc_digit ycarry = 1; 630 while (y < yend) { 631 ycarry += (~(*y++) & DIGIT_MASK); 632 (*x) = ((*x) | ycarry) & DIGIT_MASK; 633 x++; 634 ycarry >>= BITS_PER_DIGIT; 635 } 636 while (x < xend) { 637 ycarry += DIGIT_MASK; 638 (*x) = ((*x) | ycarry) & DIGIT_MASK; 639 x++; 640 ycarry >>= BITS_PER_DIGIT; 641 } 642 } else { // case 6 643 sc_digit xcarry = 1; 644 while (y < yend) { 645 xcarry += (~(*x) & DIGIT_MASK); 646 (*x++) = (xcarry | (*y++)) & DIGIT_MASK; 647 xcarry >>= BITS_PER_DIGIT; 648 } 649 while (x < xend) { 650 xcarry += (~(*x) & DIGIT_MASK); 651 (*x++) = xcarry & DIGIT_MASK; 652 xcarry >>= BITS_PER_DIGIT; 653 } 654 } 655 } 656} 657 658 659// ---------------------------------------------------------------------------- 660// SECTION: External functions for XOR operators. 661// ---------------------------------------------------------------------------- 662 663// Handles the cases 3-5 and returns the result in u. 664void 665xor_on_help(small_type us, int /* unb */, int und, sc_digit *ud, 666 small_type vs, int /* vnb */, int vnd, const sc_digit *vd) 667{ 668 sc_digit *x = ud; 669 const sc_digit *y = vd; 670 int xnd = und; 671 int ynd = vnd; 672 673 if (xnd < ynd) 674 ynd = xnd; 675 676 const sc_digit *xend = (x + xnd); 677 const sc_digit *yend = (y + ynd); 678 679 // x is longer than y. 680 small_type s = mul_signs(us, vs); 681 682 if (s > 0) { 683 if (us > 0) { // case 3 684 while (y < yend) { 685 (*x) = ((*x) ^ (*y)) & DIGIT_MASK; 686 x++; 687 y++; 688 } 689 // No change for the rest of x. 690 } else { // case 4 691 sc_digit xcarry = 1; 692 sc_digit ycarry = 1; 693 while (y < yend) { 694 xcarry += (~(*x) & DIGIT_MASK); 695 ycarry += (~(*y++) & DIGIT_MASK); 696 (*x++) = (xcarry ^ ycarry) & DIGIT_MASK; 697 xcarry >>= BITS_PER_DIGIT; 698 ycarry >>= BITS_PER_DIGIT; 699 } 700 while (x < xend) { 701 xcarry += (~(*x) & DIGIT_MASK); 702 ycarry += DIGIT_MASK; 703 (*x++) = (xcarry ^ ycarry) & DIGIT_MASK; 704 xcarry >>= BITS_PER_DIGIT; 705 ycarry >>= BITS_PER_DIGIT; 706 } 707 } 708 } else { 709 if (us > 0) { // case 5 710 sc_digit ycarry = 1; 711 while (y < yend) { 712 ycarry += (~(*y++) & DIGIT_MASK); 713 (*x) = ((*x) ^ ycarry) & DIGIT_MASK; 714 x++; 715 ycarry >>= BITS_PER_DIGIT; 716 } 717 while (x < xend) { 718 ycarry += DIGIT_MASK; 719 (*x) = ((*x) ^ ycarry) & DIGIT_MASK; 720 x++; 721 ycarry >>= BITS_PER_DIGIT; 722 } 723 } else { // case 6 724 sc_digit xcarry = 1; 725 while (y < yend) { 726 xcarry += (~(*x) & DIGIT_MASK); 727 (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK; 728 xcarry >>= BITS_PER_DIGIT; 729 } 730 while (x < xend) { 731 xcarry += (~(*x) & DIGIT_MASK); 732 (*x++) = xcarry & DIGIT_MASK; 733 xcarry >>= BITS_PER_DIGIT; 734 } 735 } 736 } 737} 738 739} // namespace sc_dt 740