1 /*****************************************************************************
2 
3   Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
4   more contributor license agreements.  See the NOTICE file distributed
5   with this work for additional information regarding copyright ownership.
6   Accellera licenses this file to you under the Apache License, Version 2.0
7   (the "License"); you may not use this file except in compliance with the
8   License.  You may obtain a copy of the License at
9 
10     http://www.apache.org/licenses/LICENSE-2.0
11 
12   Unless required by applicable law or agreed to in writing, software
13   distributed under the License is distributed on an "AS IS" BASIS,
14   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15   implied.  See the License for the specific language governing
16   permissions and limitations under the License.
17 
18  *****************************************************************************/
19 
20 /*****************************************************************************
21 
22   sc_nbexterns.cpp -- External functions for both sc_signed and sc_unsigned
23                       classes. These functions work on two parameters u and
24                       v, and copy the result to the first parameter u. This
25                       is also the reason that they are suffixed with _on_help.
26 
27   Original Author: Ali Dasdan, Synopsys, Inc.
28 
29  *****************************************************************************/
30 
31 /*****************************************************************************
32 
33   MODIFICATION LOG - modifiers, enter your name, affiliation, date and
34   changes you are making here.
35 
36       Name, Affiliation, Date:
37   Description of Modification:
38 
39  *****************************************************************************/
40 
41 
42 // $Log: sc_nbexterns.cpp,v $
43 // Revision 1.2  2011/02/18 20:19:15  acg
44 //  Andy Goodrich: updating Copyright notice.
45 //
46 // Revision 1.1.1.1  2006/12/15 20:20:05  acg
47 // SystemC 2.3
48 //
49 // Revision 1.3  2006/01/13 18:49:32  acg
50 // Added $Log command so that CVS check in comments are reproduced in the
51 // source.
52 //
53 
54 #include "sysc/datatypes/int/sc_nbexterns.h"
55 #include "sysc/kernel/sc_macros.h"
56 
57 
58 namespace sc_dt
59 {
60 
61 // ----------------------------------------------------------------------------
62 //  SECTION: External functions for PLUS operators.
63 // ----------------------------------------------------------------------------
64 
65 // Handles the cases 3 and 4 and returns the result in u.
66 void
add_on_help(small_type & us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)67 add_on_help(small_type &us, int /* unb */, int und,
68             sc_digit *ud,
69             small_type vs, int /* vnb */, int vnd,
70             const sc_digit *vd)
71 {
72 
73   vnd = vec_skip_leading_zeros(vnd, vd);
74 
75   if (us == vs) {  // case 3
76 
77     if (und >= vnd)
78       vec_add_on(und, ud, vnd, vd);
79     else
80       vec_add_on2(und, ud, vnd, vd);
81 
82   }
83   else {  // case 4
84 
85     // vec_cmp expects that und is the number of non-zero digits in ud.
86     int new_und = vec_skip_leading_zeros(und, ud);
87     int cmp_res = vec_cmp(new_und, ud, vnd, vd);
88 
89     if (cmp_res == 0)  { // u == v
90       us = SC_ZERO;
91       vec_zero(und, ud);
92       return;
93     }
94 
95     if (cmp_res > 0) // u > v
96       vec_sub_on(und, ud, vnd, vd);
97 
98     else { // u < v
99       us = -us;
100       vec_sub_on2(und, ud, vnd, vd);
101     }
102 
103   }
104 }
105 
106 
107 // ----------------------------------------------------------------------------
108 
109 /*
110 
111 mul_on_help_signed and mul_on_help_unsigned have the same body except
112 that CONVERT_SM_to_2C_to_SM and COPY_DIGITS are defined for signed and
113 unsigned, respectively.  This comment also applies to the
114 signed/unsigned versions of div_on_help and mod_on_help. It is
115 possible to take COPY_DIGITS out of these functions and create a
116 single version of each of these helper functions; however, this will
117 impose an onverhead on performance. In the versions below, any change
118 in the signed version of a helper function must be carried to a
119 corresponding change in the unsigned verion of the same function or
120 vice versa.
121 
122 */
123 
124 
125 // ----------------------------------------------------------------------------
126 //  SECTION: External functions of MULTIPLICATION operators.
127 // ----------------------------------------------------------------------------
128 
129 void
mul_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)130 mul_on_help_signed(small_type &us,
131                    int unb, int und,
132                    sc_digit *ud,
133                    int vnb, int vnd,
134                    const sc_digit *vd)
135 {
136 #define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
137 #define COPY_DIGITS copy_digits_signed
138 
139   {  // Body of mul_on_help
140 
141     int old_und = und;
142 
143     und = vec_skip_leading_zeros(und, ud);
144     vnd = vec_skip_leading_zeros(vnd, vd);
145 
146     sc_digit ud0 = (*ud);
147     sc_digit vd0 = (*vd);
148 
149     if ((vnd == 1) && (vd0 == 1)) {
150       us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
151       return;
152     }
153 
154     if ((und == 1) && (ud0 == 1)) {
155       COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
156       return;
157     }
158 
159     if ((und == 1) && (vnd == 1) &&
160         (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
161 
162       sc_digit d = ud0 * vd0;
163       COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
164       return;
165 
166     }
167 
168     int nd = und + vnd;
169 
170 #ifdef SC_MAX_NBITS
171     sc_digit d[MAX_NDIGITS];
172 #else
173     sc_digit *d = new sc_digit[nd];
174 #endif
175 
176     vec_zero(nd, d);
177 
178     if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
179       vec_mul_small(vnd, vd, ud0, d);
180 
181     else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
182       vec_mul_small(und, ud, vd0, d);
183 
184     else if (vnd < und)
185       vec_mul(und, ud, vnd, vd, d);
186 
187     else
188       vec_mul(vnd, vd, und, ud, d);
189 
190     COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
191 
192 #ifndef SC_MAX_NBITS
193     delete [] d;
194 #endif
195 
196   }
197 
198 #undef COPY_DIGITS
199 #undef CONVERT_SM_to_2C_to_SM
200 
201 }
202 
203 
204 void
mul_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)205 mul_on_help_unsigned(small_type &us,
206                      int unb, int und,
207                      sc_digit *ud,
208                      int vnb, int vnd,
209                      const sc_digit *vd)
210 {
211 #define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
212 #define COPY_DIGITS copy_digits_unsigned
213 
214   {  // Body of mul_on_help
215 
216     int old_und = und;
217 
218     und = vec_skip_leading_zeros(und, ud);
219     vnd = vec_skip_leading_zeros(vnd, vd);
220 
221     sc_digit ud0 = (*ud);
222     sc_digit vd0 = (*vd);
223 
224     if ((vnd == 1) && (vd0 == 1)) {
225       us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
226       return;
227     }
228 
229     if ((und == 1) && (ud0 == 1)) {
230       COPY_DIGITS(us, unb, old_und, ud, vnb, vnd, vd);
231       return;
232     }
233 
234     if ((und == 1) && (vnd == 1) &&
235         (ud0 < HALF_DIGIT_RADIX) && (vd0 < HALF_DIGIT_RADIX)) {
236 
237       sc_digit d = ud0 * vd0;
238       COPY_DIGITS(us, unb, old_und, ud, unb + vnb, 1, &d);
239       return;
240 
241     }
242 
243     int nd = und + vnd;
244 
245 #ifdef SC_MAX_NBITS
246     sc_digit d[MAX_NDIGITS];
247 #else
248     sc_digit *d = new sc_digit[nd];
249 #endif
250 
251     vec_zero(nd, d);
252 
253     if ((und == 1) && (ud0 < HALF_DIGIT_RADIX))
254       vec_mul_small(vnd, vd, ud0, d);
255 
256     else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
257       vec_mul_small(und, ud, vd0, d);
258 
259     else if (vnd < und)
260       vec_mul(und, ud, vnd, vd, d);
261 
262     else
263       vec_mul(vnd, vd, und, ud, d);
264 
265     COPY_DIGITS(us, unb, old_und, ud, unb + vnb, nd, d);
266 
267 #ifndef SC_MAX_NBITS
268     delete [] d;
269 #endif
270 
271   }
272 
273 #undef COPY_DIGITS
274 #undef CONVERT_SM_to_2C_to_SM
275 
276 }
277 
278 
279 // ----------------------------------------------------------------------------
280 //  SECTION: External functions for DIVISION operators.
281 // ----------------------------------------------------------------------------
282 
283 void
div_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)284 div_on_help_signed(small_type &us,
285                    int unb, int und,
286                    sc_digit *ud,
287                    int vnb, int vnd,
288                    const sc_digit *vd)
289 {
290 #define CONVERT_SM_to_2C_to_SM convert_signed_SM_to_2C_to_SM
291 #define COPY_DIGITS copy_digits_signed
292 
293   {  // Body of div_on_help
294 
295     int old_und = und;
296 
297     und = vec_skip_leading_zeros(und, ud);
298     vnd = vec_skip_leading_zeros(vnd, vd);
299 
300     int cmp_res = vec_cmp(und, ud, vnd, vd);
301 
302     if (cmp_res < 0) { // u < v => u / v = 0 - case 4
303       us = SC_ZERO;
304       vec_zero(old_und, ud);
305       return;
306     }
307 
308     sc_digit vd0 = (*vd);
309 
310     if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))  {
311       us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
312       return;
313     }
314 
315     // One extra digit for d is allocated to simplify vec_div_*().
316     int nd = sc_max(und, vnd) + 1;
317 
318 #ifdef SC_MAX_NBITS
319     sc_digit d[MAX_NDIGITS + 1];
320 #else
321     sc_digit *d = new sc_digit[nd];
322 #endif
323 
324     vec_zero(nd, d);
325 
326     // u = v => u / v = 1 - case 3
327     if (cmp_res == 0)
328       d[0] = 1;
329 
330     else if ((vnd == 1) && (und == 1))
331       d[0] = (*ud) / vd0;
332 
333     else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
334       vec_div_small(und, ud, vd0, d);
335 
336     else
337       vec_div_large(und, ud, vnd, vd, d);
338 
339     COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
340 
341 #ifndef SC_MAX_NBITS
342     delete [] d;
343 #endif
344 
345   }
346 
347 #undef COPY_DIGITS
348 #undef CONVERT_SM_to_2C_to_SM
349 
350 }
351 
352 
353 void
div_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int vnb,int vnd,const sc_digit * vd)354 div_on_help_unsigned(small_type &us,
355                      int unb, int und,
356                      sc_digit *ud,
357                      int vnb, int vnd,
358                      const sc_digit *vd)
359 {
360 #define CONVERT_SM_to_2C_to_SM convert_unsigned_SM_to_2C_to_SM
361 #define COPY_DIGITS copy_digits_unsigned
362 
363   {  // Body of div_on_help
364 
365     int old_und = und;
366 
367     und = vec_skip_leading_zeros(und, ud);
368     vnd = vec_skip_leading_zeros(vnd, vd);
369 
370     int cmp_res = vec_cmp(und, ud, vnd, vd);
371 
372     if (cmp_res < 0) { // u < v => u / v = 0 - case 4
373       us = SC_ZERO;
374       vec_zero(old_und, ud);
375       return;
376     }
377 
378     sc_digit vd0 = (*vd);
379 
380     if ((cmp_res > 0) && (vnd == 1) && (vd0 == 1))  {
381       us = CONVERT_SM_to_2C_to_SM(us, unb, old_und, ud);
382       return;
383     }
384 
385     // One extra digit for d is allocated to simplify vec_div_*().
386     int nd = sc_max(und, vnd) + 1;
387 
388 #ifdef SC_MAX_NBITS
389     sc_digit d[MAX_NDIGITS + 1];
390 #else
391     sc_digit *d = new sc_digit[nd];
392 #endif
393 
394     vec_zero(nd, d);
395 
396     // u = v => u / v = 1 - case 3
397     if (cmp_res == 0)
398       d[0] = 1;
399 
400     else if ((vnd == 1) && (und == 1))
401       d[0] = (*ud) / vd0;
402 
403     else if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
404       vec_div_small(und, ud, vd0, d);
405 
406     else
407       vec_div_large(und, ud, vnd, vd, d);
408 
409     COPY_DIGITS(us, unb, old_und, ud, sc_max(unb, vnb), nd - 1, d);
410 
411 #ifndef SC_MAX_NBITS
412     delete [] d;
413 #endif
414 
415   }
416 
417 #undef COPY_DIGITS
418 #undef CONVERT_SM_to_2C_to_SM
419 
420 }
421 
422 
423 // ----------------------------------------------------------------------------
424 //  SECTION: External functions for MOD operators.
425 // ----------------------------------------------------------------------------
426 
427 void
mod_on_help_signed(small_type & us,int unb,int und,sc_digit * ud,int,int vnd,const sc_digit * vd)428 mod_on_help_signed(small_type &us,
429                    int unb, int und,
430                    sc_digit *ud,
431                    int /* vnb */, int vnd,
432                    const sc_digit *vd)
433 {
434 
435 #define COPY_DIGITS copy_digits_signed
436 
437   { // Body of mod_on_help
438 
439     int old_und = und;
440 
441     und = vec_skip_leading_zeros(und, ud);
442     vnd = vec_skip_leading_zeros(vnd, vd);
443 
444     int cmp_res = vec_cmp(und, ud, vnd, vd);
445 
446     // u < v => u % v = u - case 4
447     if (cmp_res < 0)
448       return;
449 
450     // u = v => u % v = 0 - case 3
451     if (cmp_res == 0) {
452       us = SC_ZERO;
453       vec_zero(old_und, ud);
454       return;
455     }
456 
457     // else if u > v - case 5
458 
459     sc_digit vd0 = (*vd);
460 
461     if ((vnd == 1) && (vd0 == 1)) {
462       us = SC_ZERO;
463       vec_zero(old_und, ud);
464       return;
465     }
466 
467     // One extra digit for d is allocated to simplify vec_div_*().
468     int nd = sc_max(und, vnd) + 1;
469 
470 #ifdef SC_MAX_NBITS
471     sc_digit d[MAX_NDIGITS + 1];
472 #else
473     sc_digit *d = new sc_digit[nd];
474 #endif
475 
476     vec_zero(nd, d);
477 
478     if ((vnd == 1) && (und == 1))
479       d[0] = (*ud) % vd0;
480 
481     if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
482       d[0] = vec_rem_small(und, ud, vd0);
483 
484     else
485       vec_rem_large(und, ud, vnd, vd, d);
486 
487     us = check_for_zero(us, nd - 1, d);
488 
489     if (us == SC_ZERO)
490       vec_zero(old_und, ud);
491     else
492       COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
493 
494 #ifndef SC_MAX_NBITS
495     delete [] d;
496 #endif
497 
498   }
499 
500 #undef COPY_DIGITS
501 
502 }
503 
504 
505 void
mod_on_help_unsigned(small_type & us,int unb,int und,sc_digit * ud,int,int vnd,const sc_digit * vd)506 mod_on_help_unsigned(small_type &us,
507                      int unb, int und,
508                      sc_digit *ud,
509                      int /* vnb */, int vnd,
510                      const sc_digit *vd)
511 {
512 
513 #define COPY_DIGITS copy_digits_unsigned
514 
515   { // Body of mod_on_help
516 
517     int old_und = und;
518 
519     und = vec_skip_leading_zeros(und, ud);
520     vnd = vec_skip_leading_zeros(vnd, vd);
521 
522     int cmp_res = vec_cmp(und, ud, vnd, vd);
523 
524     // u < v => u % v = u - case 4
525     if (cmp_res < 0)
526       return;
527 
528     // u = v => u % v = 0 - case 3
529     if (cmp_res == 0) {
530       us = SC_ZERO;
531       vec_zero(old_und, ud);
532       return;
533     }
534 
535     // else if u > v - case 5
536 
537     sc_digit vd0 = (*vd);
538 
539     if ((vnd == 1) && (vd0 == 1)) {
540       us = SC_ZERO;
541       vec_zero(old_und, ud);
542       return;
543     }
544 
545     // One extra digit for d is allocated to simplify vec_div_*().
546     int nd = sc_max(und, vnd) + 1;
547 
548 #ifdef SC_MAX_NBITS
549     sc_digit d[MAX_NDIGITS + 1];
550 #else
551     sc_digit *d = new sc_digit[nd];
552 #endif
553 
554     vec_zero(nd, d);
555 
556     if ((vnd == 1) && (und == 1))
557       d[0] = (*ud) % vd0;
558 
559     if ((vnd == 1) && (vd0 < HALF_DIGIT_RADIX))
560       d[0] = vec_rem_small(und, ud, vd0);
561 
562     else
563       vec_rem_large(und, ud, vnd, vd, d);
564 
565     us = check_for_zero(us, nd - 1, d);
566 
567     if (us == SC_ZERO)
568       vec_zero(old_und, ud);
569     else
570       COPY_DIGITS(us, unb, old_und, ud, sc_min(unb, vnd), nd - 1, d);
571 
572 #ifndef SC_MAX_NBITS
573     delete [] d;
574 #endif
575 
576   }
577 
578 #undef COPY_DIGITS
579 
580 }
581 
582 
583 // ----------------------------------------------------------------------------
584 //  SECTION: External functions for AND operators.
585 // ----------------------------------------------------------------------------
586 
587 // Handles the cases 2-5 and returns the result in u.
588 void
and_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)589 and_on_help(small_type us,
590             int /* unb */, int und,
591             sc_digit *ud,
592             small_type vs,
593             int /* vnb */, int vnd,
594             const sc_digit *vd)
595 {
596 
597   sc_digit *x = ud;
598   const sc_digit *y = vd;
599   int xnd = und;
600   int ynd = vnd;
601 
602   // Truncate y.
603   if (xnd < ynd)
604     ynd = xnd;
605 
606   const sc_digit *xend = (x + xnd);
607   const sc_digit *yend = (y + ynd);
608 
609   // x is longer than y.
610 
611   small_type s = mul_signs(us, vs);
612 
613   if (s > 0) {
614 
615     if (us > 0) { // case 2
616 
617       while (y < yend)
618         (*x++) &= (*y++);
619 
620       while (x < xend)
621         (*x++) = 0;
622 
623     }
624     else {  // case 3
625 
626       sc_digit xcarry = 1;
627       sc_digit ycarry = 1;
628 
629       while (y < yend) {
630         xcarry += (~(*x) & DIGIT_MASK);
631         ycarry += (~(*y++) & DIGIT_MASK);
632         (*x++) = (xcarry & ycarry) & DIGIT_MASK;
633         xcarry >>= BITS_PER_DIGIT;
634         ycarry >>= BITS_PER_DIGIT;
635       }
636 
637       while (x < xend) {
638         xcarry += (~(*x) & DIGIT_MASK);
639         ycarry += DIGIT_MASK;
640         (*x++) = (xcarry & ycarry) & DIGIT_MASK;
641         xcarry >>= BITS_PER_DIGIT;
642         ycarry >>= BITS_PER_DIGIT;
643       }
644 
645     }
646   }
647   else {
648 
649     if (us > 0) { // case 4
650 
651       sc_digit ycarry = 1;
652 
653       while (y < yend) {
654         ycarry += (~(*y++) & DIGIT_MASK);
655         (*x++) &= ycarry & DIGIT_MASK;
656         ycarry >>= BITS_PER_DIGIT;
657       }
658 
659       while (x < xend) {
660         ycarry += DIGIT_MASK;
661         (*x++) &= ycarry & DIGIT_MASK;
662         ycarry >>= BITS_PER_DIGIT;
663       }
664 
665     }
666     else {  // case 5
667 
668       sc_digit xcarry = 1;
669 
670       while (y < yend) {
671         xcarry += (~(*x) & DIGIT_MASK);
672         (*x++) = (xcarry & (*y++)) & DIGIT_MASK;
673         xcarry >>= BITS_PER_DIGIT;
674       }
675 
676       while (x < xend)
677         (*x++) = 0;
678 
679     }
680   }
681 }
682 
683 
684 // ----------------------------------------------------------------------------
685 //  SECTION: External functions for OR operators.
686 // ----------------------------------------------------------------------------
687 
688 // Handles the cases 3-5 and returns the result in u.
689 void
or_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)690 or_on_help(small_type us,
691            int /* unb */, int und,
692            sc_digit *ud,
693            small_type vs,
694            int /* vnb */, int vnd,
695            const sc_digit *vd)
696 {
697 
698   sc_digit *x = ud;
699   const sc_digit *y = vd;
700   int xnd = und;
701   int ynd = vnd;
702 
703   if (xnd < ynd)
704     ynd = xnd;
705 
706   const sc_digit *xend = (x + xnd);
707   const sc_digit *yend = (y + ynd);
708 
709   // x is longer than y.
710 
711   small_type s = mul_signs(us, vs);
712 
713   if (s > 0) {
714 
715     if (us > 0) { // case 3
716 
717       while (y < yend)
718         (*x++) |= (*y++);
719 
720       // No change for the rest of x.
721 
722     }
723     else {  // case 4
724 
725       sc_digit xcarry = 1;
726       sc_digit ycarry = 1;
727 
728       while (y < yend) {
729         xcarry += (~(*x) & DIGIT_MASK);
730         ycarry += (~(*y++) & DIGIT_MASK);
731         (*x++) = (xcarry | ycarry) & DIGIT_MASK;
732         xcarry >>= BITS_PER_DIGIT;
733         ycarry >>= BITS_PER_DIGIT;
734       }
735 
736       while (x < xend) {
737         xcarry += (~(*x) & DIGIT_MASK);
738         ycarry += DIGIT_MASK;
739         (*x++) = (xcarry | ycarry) & DIGIT_MASK;
740         xcarry >>= BITS_PER_DIGIT;
741         ycarry >>= BITS_PER_DIGIT;
742       }
743     }
744 
745   }
746   else {
747 
748     if (us > 0) { // case 5
749 
750       sc_digit ycarry = 1;
751 
752       while (y < yend) {
753         ycarry += (~(*y++) & DIGIT_MASK);
754         (*x) = ((*x) | ycarry) & DIGIT_MASK;
755         x++;
756         ycarry >>= BITS_PER_DIGIT;
757       }
758 
759       while (x < xend) {
760         ycarry += DIGIT_MASK;
761         (*x) = ((*x) | ycarry) & DIGIT_MASK;
762         x++;
763         ycarry >>= BITS_PER_DIGIT;
764       }
765 
766     }
767     else {  // case 6
768 
769       sc_digit xcarry = 1;
770 
771       while (y < yend) {
772         xcarry += (~(*x) & DIGIT_MASK);
773         (*x++) = (xcarry | (*y++)) & DIGIT_MASK;
774         xcarry >>= BITS_PER_DIGIT;
775       }
776 
777       while (x < xend) {
778         xcarry += (~(*x) & DIGIT_MASK);
779         (*x++) = xcarry & DIGIT_MASK;
780         xcarry >>= BITS_PER_DIGIT;
781       }
782     }
783   }
784 }
785 
786 
787 // ----------------------------------------------------------------------------
788 //  SECTION: External functions for XOR operators.
789 // ----------------------------------------------------------------------------
790 
791 // Handles the cases 3-5 and returns the result in u.
792 void
xor_on_help(small_type us,int,int und,sc_digit * ud,small_type vs,int,int vnd,const sc_digit * vd)793 xor_on_help(small_type us,
794             int /* unb */, int und,
795             sc_digit *ud,
796             small_type vs,
797             int /* vnb */, int vnd,
798             const sc_digit *vd)
799 {
800 
801   sc_digit *x = ud;
802   const sc_digit *y = vd;
803   int xnd = und;
804   int ynd = vnd;
805 
806   if (xnd < ynd)
807     ynd = xnd;
808 
809   const sc_digit *xend = (x + xnd);
810   const sc_digit *yend = (y + ynd);
811 
812   // x is longer than y.
813 
814   small_type s = mul_signs(us, vs);
815 
816   if (s > 0) {
817 
818     if (us > 0) { // case 3
819 
820       while (y < yend) {
821         (*x) = ((*x) ^ (*y)) & DIGIT_MASK;
822         x++;
823         y++;
824       }
825 
826       // No change for the rest of x.
827 
828     }
829     else {  // case 4
830 
831       sc_digit xcarry = 1;
832       sc_digit ycarry = 1;
833 
834       while (y < yend) {
835         xcarry += (~(*x) & DIGIT_MASK);
836         ycarry += (~(*y++) & DIGIT_MASK);
837         (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
838         xcarry >>= BITS_PER_DIGIT;
839         ycarry >>= BITS_PER_DIGIT;
840       }
841 
842       while (x < xend) {
843         xcarry += (~(*x) & DIGIT_MASK);
844         ycarry += DIGIT_MASK;
845         (*x++) = (xcarry ^ ycarry) & DIGIT_MASK;
846         xcarry >>= BITS_PER_DIGIT;
847         ycarry >>= BITS_PER_DIGIT;
848       }
849     }
850   }
851   else {
852 
853     if (us > 0) { // case 5
854 
855       sc_digit ycarry = 1;
856 
857       while (y < yend) {
858         ycarry += (~(*y++) & DIGIT_MASK);
859         (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
860         x++;
861         ycarry >>= BITS_PER_DIGIT;
862       }
863 
864       while (x < xend) {
865         ycarry += DIGIT_MASK;
866         (*x) = ((*x) ^ ycarry) & DIGIT_MASK;
867         x++;
868         ycarry >>= BITS_PER_DIGIT;
869       }
870 
871     }
872     else {  // case 6
873 
874       sc_digit xcarry = 1;
875 
876       while (y < yend) {
877         xcarry += (~(*x) & DIGIT_MASK);
878         (*x++) = (xcarry ^ (*y++)) & DIGIT_MASK;
879         xcarry >>= BITS_PER_DIGIT;
880       }
881 
882       while (x < xend) {
883         xcarry += (~(*x) & DIGIT_MASK);
884         (*x++) = xcarry & DIGIT_MASK;
885         xcarry >>= BITS_PER_DIGIT;
886       }
887     }
888   }
889 }
890 
891 } // namespace sc_dt
892 
893 
894 // End of file
895