GEOS  3.8.0dev
ttmathuint_x86_64.h
1 /*
2  * This file is a part of TTMath Bignum Library
3  * and is distributed under the 3-Clause BSD Licence.
4  * Author: Tomasz Sowa <t.sowa@ttmath.org>
5  */
6 
7 /*
8  * Copyright (c) 2006-2010, Tomasz Sowa
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions are met:
13  *
14  * * Redistributions of source code must retain the above copyright notice,
15  * this list of conditions and the following disclaimer.
16  *
17  * * Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * * Neither the name Tomasz Sowa nor the names of contributors to this
22  * project may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
29  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35  * THE POSSIBILITY OF SUCH DAMAGE.
36  */
37 
38 
39 #ifndef headerfilettmathuint_x86_64
40 #define headerfilettmathuint_x86_64
41 
42 
43 #ifndef TTMATH_NOASM
44 #ifdef TTMATH_PLATFORM64
45 
46 
69 #ifndef __GNUC__
70 #include <intrin.h>
71 #endif
72 
73 
74 namespace ttmath
75 {
76 
77  #ifndef __GNUC__
78 
79  extern "C"
80  {
81  uint __fastcall ttmath_adc_x64(uint* p1, const uint* p2, uint nSize, uint c);
82  uint __fastcall ttmath_addindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
83  uint __fastcall ttmath_addindexed2_x64(uint* p1, uint nSize, uint nPos, uint nValue1, uint nValue2);
84  uint __fastcall ttmath_addvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
85  uint __fastcall ttmath_sbb_x64(uint* p1, const uint* p2, uint nSize, uint c);
86  uint __fastcall ttmath_subindexed_x64(uint* p1, uint nSize, uint nPos, uint nValue);
87  uint __fastcall ttmath_subvector_x64(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result);
88  uint __fastcall ttmath_rcl_x64(uint* p1, uint nSize, uint nLowestBit);
89  uint __fastcall ttmath_rcr_x64(uint* p1, uint nSize, uint nLowestBit);
90  uint __fastcall ttmath_div_x64(uint* pnValHi, uint* pnValLo, uint nDiv);
91  uint __fastcall ttmath_rcl2_x64(uint* p1, uint nSize, uint nBits, uint c);
92  uint __fastcall ttmath_rcr2_x64(uint* p1, uint nSize, uint nBits, uint c);
93  };
94  #endif
95 
96 
107  template<uint value_size>
108  const char * UInt<value_size>::LibTypeStr()
109  {
110  #ifndef __GNUC__
111  static const char info[] = "asm_vc_64";
112  #endif
113 
114  #ifdef __GNUC__
115  static const char info[] = "asm_gcc_64";
116  #endif
117 
118  return info;
119  }
120 
121 
125  template<uint value_size>
126  LibTypeCode UInt<value_size>::LibType()
127  {
128  #ifndef __GNUC__
129  LibTypeCode info = asm_vc_64;
130  #endif
131 
132  #ifdef __GNUC__
133  LibTypeCode info = asm_gcc_64;
134  #endif
135 
136  return info;
137  }
138 
139 
157  template<uint value_size>
158  uint UInt<value_size>::Add(const UInt<value_size> & ss2, uint c)
159  {
160  uint b = value_size;
161  uint * p1 = table;
162  const uint * p2 = ss2.table;
163 
164  // we don't have to use TTMATH_REFERENCE_ASSERT here
165  // this algorithm doesn't require it
166 
167  #ifndef __GNUC__
168  c = ttmath_adc_x64(p1,p2,b,c);
169  #endif
170 
171  #ifdef __GNUC__
172  uint dummy, dummy2;
173 
174  /*
175  this part should be compiled with gcc
176  */
177  __asm__ __volatile__(
178 
179  "xorq %%rdx, %%rdx \n"
180  "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
181 
182  "1: \n"
183  "movq (%%rsi,%%rdx,8), %%rax \n"
184  "adcq %%rax, (%%rbx,%%rdx,8) \n"
185 
186  "incq %%rdx \n"
187  "decq %%rcx \n"
188  "jnz 1b \n"
189 
190  "adcq %%rcx, %%rcx \n"
191 
192  : "=c" (c), "=a" (dummy), "=d" (dummy2)
193  : "0" (b), "1" (c), "b" (p1), "S" (p2)
194  : "cc", "memory" );
195 
196  #endif
197 
198  TTMATH_LOGC("UInt::Add", c)
199 
200  return c;
201  }
202 
203 
204 
230  template<uint value_size>
231  uint UInt<value_size>::AddInt(uint value, uint index)
232  {
233  uint b = value_size;
234  uint * p1 = table;
235  uint c;
236 
237  TTMATH_ASSERT( index < value_size )
238 
239  #ifndef __GNUC__
240  c = ttmath_addindexed_x64(p1,b,index,value);
241  #endif
242 
243 
244  #ifdef __GNUC__
245  uint dummy, dummy2;
246 
247  __asm__ __volatile__(
248 
249  "subq %%rdx, %%rcx \n"
250 
251  "1: \n"
252  "addq %%rax, (%%rbx,%%rdx,8) \n"
253  "jnc 2f \n"
254 
255  "movq $1, %%rax \n"
256  "incq %%rdx \n"
257  "decq %%rcx \n"
258  "jnz 1b \n"
259 
260  "2: \n"
261  "setc %%al \n"
262  "movzx %%al, %%rdx \n"
263 
264  : "=d" (c), "=a" (dummy), "=c" (dummy2)
265  : "0" (index), "1" (value), "2" (b), "b" (p1)
266  : "cc", "memory" );
267 
268  #endif
269 
270  TTMATH_LOGC("UInt::AddInt", c)
271 
272  return c;
273  }
274 
275 
276 
315  template<uint value_size>
316  uint UInt<value_size>::AddTwoInts(uint x2, uint x1, uint index)
317  {
318  uint b = value_size;
319  uint * p1 = table;
320  uint c;
321 
322  TTMATH_ASSERT( index < value_size - 1 )
323 
324  #ifndef __GNUC__
325  c = ttmath_addindexed2_x64(p1,b,index,x1,x2);
326  #endif
327 
328 
329  #ifdef __GNUC__
330  uint dummy, dummy2;
331 
332  __asm__ __volatile__(
333 
334  "subq %%rdx, %%rcx \n"
335 
336  "addq %%rsi, (%%rbx,%%rdx,8) \n"
337  "incq %%rdx \n"
338  "decq %%rcx \n"
339 
340  "1: \n"
341  "adcq %%rax, (%%rbx,%%rdx,8) \n"
342  "jnc 2f \n"
343 
344  "mov $0, %%rax \n"
345  "incq %%rdx \n"
346  "decq %%rcx \n"
347  "jnz 1b \n"
348 
349  "2: \n"
350  "setc %%al \n"
351  "movzx %%al, %%rax \n"
352 
353  : "=a" (c), "=c" (dummy), "=d" (dummy2)
354  : "0" (x2), "1" (b), "2" (index), "b" (p1), "S" (x1)
355  : "cc", "memory" );
356 
357  #endif
358 
359  TTMATH_LOGC("UInt::AddTwoInts", c)
360 
361  return c;
362  }
363 
364 
365 
386  template<uint value_size>
387  uint UInt<value_size>::AddVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
388  {
389  TTMATH_ASSERT( ss1_size >= ss2_size )
390 
391  uint c;
392 
393  #ifndef __GNUC__
394  c = ttmath_addvector_x64(ss1, ss2, ss1_size, ss2_size, result);
395  #endif
396 
397 
398  #ifdef __GNUC__
399  uint dummy1, dummy2, dummy3;
400  uint rest = ss1_size - ss2_size;
401 
402  // this part should be compiled with gcc
403 
404  __asm__ __volatile__(
405  "mov %%rdx, %%r8 \n"
406  "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
407  "1: \n"
408  "mov (%%rsi,%%rdx,8), %%rax \n"
409  "adc (%%rbx,%%rdx,8), %%rax \n"
410  "mov %%rax, (%%rdi,%%rdx,8) \n"
411 
412  "inc %%rdx \n"
413  "dec %%rcx \n"
414  "jnz 1b \n"
415 
416  "adc %%rcx, %%rcx \n" // rcx has the cf state
417 
418  "or %%r8, %%r8 \n"
419  "jz 3f \n"
420 
421  "xor %%rbx, %%rbx \n" // ebx = 0
422  "neg %%rcx \n" // setting cf from rcx
423  "mov %%r8, %%rcx \n" // rcx=rest and is != 0
424  "2: \n"
425  "mov (%%rsi, %%rdx, 8), %%rax \n"
426  "adc %%rbx, %%rax \n"
427  "mov %%rax, (%%rdi, %%rdx, 8) \n"
428 
429  "inc %%rdx \n"
430  "dec %%rcx \n"
431  "jnz 2b \n"
432 
433  "adc %%rcx, %%rcx \n"
434  "3: \n"
435 
436  : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
437  : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
438  : "%r8", "cc", "memory" );
439 
440  #endif
441 
442  TTMATH_VECTOR_LOGC("UInt::AddVector", c, result, ss1_size)
443 
444  return c;
445  }
446 
447 
448 
459  template<uint value_size>
460  uint UInt<value_size>::Sub(const UInt<value_size> & ss2, uint c)
461  {
462  uint b = value_size;
463  uint * p1 = table;
464  const uint * p2 = ss2.table;
465 
466  // we don't have to use TTMATH_REFERENCE_ASSERT here
467  // this algorithm doesn't require it
468 
469  #ifndef __GNUC__
470  c = ttmath_sbb_x64(p1,p2,b,c);
471  #endif
472 
473 
474  #ifdef __GNUC__
475  uint dummy, dummy2;
476 
477  __asm__ __volatile__(
478 
479  "xorq %%rdx, %%rdx \n"
480  "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
481 
482  "1: \n"
483  "movq (%%rsi,%%rdx,8), %%rax \n"
484  "sbbq %%rax, (%%rbx,%%rdx,8) \n"
485 
486  "incq %%rdx \n"
487  "decq %%rcx \n"
488  "jnz 1b \n"
489 
490  "adcq %%rcx, %%rcx \n"
491 
492  : "=c" (c), "=a" (dummy), "=d" (dummy2)
493  : "0" (b), "1" (c), "b" (p1), "S" (p2)
494  : "cc", "memory" );
495 
496  #endif
497 
498  TTMATH_LOGC("UInt::Sub", c)
499 
500  return c;
501  }
502 
503 
504 
529  template<uint value_size>
530  uint UInt<value_size>::SubInt(uint value, uint index)
531  {
532  uint b = value_size;
533  uint * p1 = table;
534  uint c;
535 
536  TTMATH_ASSERT( index < value_size )
537 
538  #ifndef __GNUC__
539  c = ttmath_subindexed_x64(p1,b,index,value);
540  #endif
541 
542 
543  #ifdef __GNUC__
544  uint dummy, dummy2;
545 
546  __asm__ __volatile__(
547 
548  "subq %%rdx, %%rcx \n"
549 
550  "1: \n"
551  "subq %%rax, (%%rbx,%%rdx,8) \n"
552  "jnc 2f \n"
553 
554  "movq $1, %%rax \n"
555  "incq %%rdx \n"
556  "decq %%rcx \n"
557  "jnz 1b \n"
558 
559  "2: \n"
560  "setc %%al \n"
561  "movzx %%al, %%rdx \n"
562 
563  : "=d" (c), "=a" (dummy), "=c" (dummy2)
564  : "0" (index), "1" (value), "2" (b), "b" (p1)
565  : "cc", "memory" );
566 
567  #endif
568 
569  TTMATH_LOGC("UInt::SubInt", c)
570 
571  return c;
572  }
573 
574 
596  template<uint value_size>
597  uint UInt<value_size>::SubVector(const uint * ss1, const uint * ss2, uint ss1_size, uint ss2_size, uint * result)
598  {
599  TTMATH_ASSERT( ss1_size >= ss2_size )
600 
601  uint c;
602 
603  #ifndef __GNUC__
604  c = ttmath_subvector_x64(ss1, ss2, ss1_size, ss2_size, result);
605  #endif
606 
607 
608  #ifdef __GNUC__
609 
610  // the asm code is nearly the same as in AddVector
611  // only two instructions 'adc' are changed to 'sbb'
612 
613  uint dummy1, dummy2, dummy3;
614  uint rest = ss1_size - ss2_size;
615 
616  __asm__ __volatile__(
617  "mov %%rdx, %%r8 \n"
618  "xor %%rdx, %%rdx \n" // rdx = 0, cf = 0
619  "1: \n"
620  "mov (%%rsi,%%rdx,8), %%rax \n"
621  "sbb (%%rbx,%%rdx,8), %%rax \n"
622  "mov %%rax, (%%rdi,%%rdx,8) \n"
623 
624  "inc %%rdx \n"
625  "dec %%rcx \n"
626  "jnz 1b \n"
627 
628  "adc %%rcx, %%rcx \n" // rcx has the cf state
629 
630  "or %%r8, %%r8 \n"
631  "jz 3f \n"
632 
633  "xor %%rbx, %%rbx \n" // ebx = 0
634  "neg %%rcx \n" // setting cf from rcx
635  "mov %%r8, %%rcx \n" // rcx=rest and is != 0
636  "2: \n"
637  "mov (%%rsi, %%rdx, 8), %%rax \n"
638  "sbb %%rbx, %%rax \n"
639  "mov %%rax, (%%rdi, %%rdx, 8) \n"
640 
641  "inc %%rdx \n"
642  "dec %%rcx \n"
643  "jnz 2b \n"
644 
645  "adc %%rcx, %%rcx \n"
646  "3: \n"
647 
648  : "=a" (dummy1), "=b" (dummy2), "=c" (c), "=d" (dummy3)
649  : "1" (ss2), "2" (ss2_size), "3" (rest), "S" (ss1), "D" (result)
650  : "%r8", "cc", "memory" );
651 
652  #endif
653 
654  TTMATH_VECTOR_LOGC("UInt::SubVector", c, result, ss1_size)
655 
656  return c;
657  }
658 
659 
674  template<uint value_size>
675  uint UInt<value_size>::Rcl2_one(uint c)
676  {
677  sint b = value_size;
678  uint * p1 = table;
679 
680 
681  #ifndef __GNUC__
682  c = ttmath_rcl_x64(p1,b,c);
683  #endif
684 
685 
686  #ifdef __GNUC__
687  uint dummy, dummy2;
688 
689  __asm__ __volatile__(
690 
691  "xorq %%rdx, %%rdx \n" // rdx=0
692  "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
693 
694  "1: \n"
695  "rclq $1, (%%rbx, %%rdx, 8) \n"
696 
697  "incq %%rdx \n"
698  "decq %%rcx \n"
699  "jnz 1b \n"
700 
701  "adcq %%rcx, %%rcx \n"
702 
703  : "=c" (c), "=a" (dummy), "=d" (dummy2)
704  : "0" (b), "1" (c), "b" (p1)
705  : "cc", "memory" );
706 
707  #endif
708 
709  TTMATH_LOGC("UInt::Rcl2_one", c)
710 
711  return c;
712  }
713 
714 
729  template<uint value_size>
730  uint UInt<value_size>::Rcr2_one(uint c)
731  {
732  sint b = value_size;
733  uint * p1 = table;
734 
735 
736  #ifndef __GNUC__
737  c = ttmath_rcr_x64(p1,b,c);
738  #endif
739 
740 
741  #ifdef __GNUC__
742  uint dummy;
743 
744  __asm__ __volatile__(
745 
746  "negq %%rax \n" // CF=1 if rax!=0 , CF=0 if rax==0
747 
748  "1: \n"
749  "rcrq $1, -8(%%rbx, %%rcx, 8) \n"
750 
751  "decq %%rcx \n"
752  "jnz 1b \n"
753 
754  "adcq %%rcx, %%rcx \n"
755 
756  : "=c" (c), "=a" (dummy)
757  : "0" (b), "1" (c), "b" (p1)
758  : "cc", "memory" );
759 
760  #endif
761 
762  TTMATH_LOGC("UInt::Rcr2_one", c)
763 
764  return c;
765  }
766 
767 
768 
783  template<uint value_size>
784  uint UInt<value_size>::Rcl2(uint bits, uint c)
785  {
786  TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
787 
788  uint b = value_size;
789  uint * p1 = table;
790 
791 
792  #ifndef __GNUC__
793  c = ttmath_rcl2_x64(p1,b,bits,c);
794  #endif
795 
796 
797  #ifdef __GNUC__
798  uint dummy, dummy2, dummy3;
799 
800  __asm__ __volatile__(
801 
802  "movq %%rcx, %%rsi \n"
803  "movq $64, %%rcx \n"
804  "subq %%rsi, %%rcx \n"
805  "movq $-1, %%rdx \n"
806  "shrq %%cl, %%rdx \n"
807  "movq %%rdx, %%r8 \n"
808  "movq %%rsi, %%rcx \n"
809 
810  "xorq %%rdx, %%rdx \n"
811  "movq %%rdx, %%rsi \n"
812  "orq %%rax, %%rax \n"
813  "cmovnz %%r8, %%rsi \n"
814 
815  "1: \n"
816  "rolq %%cl, (%%rbx,%%rdx,8) \n"
817 
818  "movq (%%rbx,%%rdx,8), %%rax \n"
819  "andq %%r8, %%rax \n"
820  "xorq %%rax, (%%rbx,%%rdx,8) \n"
821  "orq %%rsi, (%%rbx,%%rdx,8) \n"
822  "movq %%rax, %%rsi \n"
823 
824  "incq %%rdx \n"
825  "decq %%rdi \n"
826  "jnz 1b \n"
827 
828  "and $1, %%rax \n"
829 
830  : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
831  : "0" (c), "1" (b), "b" (p1), "c" (bits)
832  : "%r8", "cc", "memory" );
833 
834  #endif
835 
836  TTMATH_LOGC("UInt::Rcl2", c)
837 
838  return c;
839  }
840 
841 
856  template<uint value_size>
857  uint UInt<value_size>::Rcr2(uint bits, uint c)
858  {
859  TTMATH_ASSERT( bits>0 && bits<TTMATH_BITS_PER_UINT )
860 
861  sint b = value_size;
862  uint * p1 = table;
863 
864 
865  #ifndef __GNUC__
866  c = ttmath_rcr2_x64(p1,b,bits,c);
867  #endif
868 
869 
870  #ifdef __GNUC__
871  uint dummy, dummy2, dummy3;
872 
873  __asm__ __volatile__(
874 
875  "movq %%rcx, %%rsi \n"
876  "movq $64, %%rcx \n"
877  "subq %%rsi, %%rcx \n"
878  "movq $-1, %%rdx \n"
879  "shlq %%cl, %%rdx \n"
880  "movq %%rdx, %%R8 \n"
881  "movq %%rsi, %%rcx \n"
882 
883  "xorq %%rdx, %%rdx \n"
884  "movq %%rdx, %%rsi \n"
885  "addq %%rdi, %%rdx \n"
886  "decq %%rdx \n"
887  "orq %%rax, %%rax \n"
888  "cmovnz %%R8, %%rsi \n"
889 
890  "1: \n"
891  "rorq %%cl, (%%rbx,%%rdx,8) \n"
892 
893  "movq (%%rbx,%%rdx,8), %%rax \n"
894  "andq %%R8, %%rax \n"
895  "xorq %%rax, (%%rbx,%%rdx,8) \n"
896  "orq %%rsi, (%%rbx,%%rdx,8) \n"
897  "movq %%rax, %%rsi \n"
898 
899  "decq %%rdx \n"
900  "decq %%rdi \n"
901  "jnz 1b \n"
902 
903  "rolq $1, %%rax \n"
904  "andq $1, %%rax \n"
905 
906  : "=a" (c), "=D" (dummy), "=S" (dummy2), "=d" (dummy3)
907  : "0" (c), "1" (b), "b" (p1), "c" (bits)
908  : "%r8", "cc", "memory" );
909 
910  #endif
911 
912  TTMATH_LOGC("UInt::Rcr2", c)
913 
914  return c;
915  }
916 
917 
918  /*
919  this method returns the number of the highest set bit in one 64-bit word
920  if the 'x' is zero this method returns '-1'
921 
922  ***this method is created only on a 64bit platform***
923  */
924  template<uint value_size>
925  sint UInt<value_size>::FindLeadingBitInWord(uint x)
926  {
927  sint result;
928 
929 
930  #ifndef __GNUC__
931 
932  unsigned long nIndex = 0;
933 
934  if( _BitScanReverse64(&nIndex,x) == 0 )
935  result = -1;
936  else
937  result = nIndex;
938 
939  #endif
940 
941 
942  #ifdef __GNUC__
943  uint dummy;
944 
945  __asm__ (
946 
947  "movq $-1, %1 \n"
948  "bsrq %2, %0 \n"
949  "cmovz %1, %0 \n"
950 
951  : "=r" (result), "=&r" (dummy)
952  : "r" (x)
953  : "cc" );
954 
955  #endif
956 
957 
958  return result;
959  }
960 
961 
962  /*
963  this method returns the number of the highest set bit in one 64-bit word
964  if the 'x' is zero this method returns '-1'
965 
966  ***this method is created only on a 64bit platform***
967  */
968  template<uint value_size>
969  sint UInt<value_size>::FindLowestBitInWord(uint x)
970  {
971  sint result;
972 
973 
974  #ifndef __GNUC__
975 
976  unsigned long nIndex = 0;
977 
978  if( _BitScanForward64(&nIndex,x) == 0 )
979  result = -1;
980  else
981  result = nIndex;
982 
983  #endif
984 
985 
986  #ifdef __GNUC__
987  uint dummy;
988 
989  __asm__ (
990 
991  "movq $-1, %1 \n"
992  "bsfq %2, %0 \n"
993  "cmovz %1, %0 \n"
994 
995  : "=r" (result), "=&r" (dummy)
996  : "r" (x)
997  : "cc" );
998 
999  #endif
1000 
1001 
1002  return result;
1003  }
1004 
1005 
1019  template<uint value_size>
1020  uint UInt<value_size>::SetBitInWord(uint & value, uint bit)
1021  {
1022  TTMATH_ASSERT( bit < TTMATH_BITS_PER_UINT )
1023 
1024  uint old_bit;
1025  uint v = value;
1026 
1027 
1028  #ifndef __GNUC__
1029  old_bit = _bittestandset64((__int64*)&value,bit) != 0;
1030  #endif
1031 
1032 
1033  #ifdef __GNUC__
1034 
1035  __asm__ (
1036 
1037  "btsq %%rbx, %%rax \n"
1038  "setc %%bl \n"
1039  "movzx %%bl, %%rbx \n"
1040 
1041  : "=a" (v), "=b" (old_bit)
1042  : "0" (v), "1" (bit)
1043  : "cc" );
1044 
1045  #endif
1046 
1047  value = v;
1048 
1049  return old_bit;
1050  }
1051 
1052 
1071  template<uint value_size>
1072  void UInt<value_size>::MulTwoWords(uint a, uint b, uint * result_high, uint * result_low)
1073  {
1074  /*
1075  we must use these temporary variables in order to inform the compilator
1076  that value pointed with result1 and result2 has changed
1077 
1078  this has no effect in visual studio but it's usefull when
1079  using gcc and options like -O
1080  */
1081  uint result1_;
1082  uint result2_;
1083 
1084 
1085  #ifndef __GNUC__
1086  result1_ = _umul128(a,b,&result2_);
1087  #endif
1088 
1089 
1090  #ifdef __GNUC__
1091 
1092  __asm__ (
1093 
1094  "mulq %%rdx \n"
1095 
1096  : "=a" (result1_), "=d" (result2_)
1097  : "0" (a), "1" (b)
1098  : "cc" );
1099 
1100  #endif
1101 
1102 
1103  *result_low = result1_;
1104  *result_high = result2_;
1105  }
1106 
1107 
1108 
1109 
1131  template<uint value_size>
1132  void UInt<value_size>::DivTwoWords(uint a,uint b, uint c, uint * r, uint * rest)
1133  {
1134  uint r_;
1135  uint rest_;
1136  /*
1137  these variables have similar meaning like those in
1138  the multiplication algorithm MulTwoWords
1139  */
1140 
1141  TTMATH_ASSERT( c != 0 )
1142 
1143 
1144  #ifndef __GNUC__
1145 
1146  ttmath_div_x64(&a,&b,c);
1147  r_ = a;
1148  rest_ = b;
1149 
1150  #endif
1151 
1152 
1153  #ifdef __GNUC__
1154 
1155  __asm__ (
1156 
1157  "divq %%rcx \n"
1158 
1159  : "=a" (r_), "=d" (rest_)
1160  : "d" (a), "a" (b), "c" (c)
1161  : "cc" );
1162 
1163  #endif
1164 
1165 
1166  *r = r_;
1167  *rest = rest_;
1168  }
1169 
1170 } //namespace
1171 
1172 
1173 #endif //ifdef TTMATH_PLATFORM64
1174 #endif //ifndef TTMATH_NOASM
1175 #endif
1176 
1177 
a namespace for the TTMath library
Definition: ttmath.h:62
LibTypeCode
Definition: ttmathtypes.h:368
#define TTMATH_BITS_PER_UINT
Definition: ttmathtypes.h:207
unsigned int uint
Definition: ttmathtypes.h:186