1 /***************************************************************************************************
2  * 
3  * Supplementary integer math functions.
4  * 
5  * Authors:
6  *   $(LINK2 mailto:Marco.Leise@gmx.de, Marco Leise)
7  * 
8  * Copyright:
9  *   © 2017 $(LINK2 mailto:Marco.Leise@gmx.de, Marco Leise)
10  * 
11  * License:
12  *   $(LINK2 http://www.gnu.org/licenses/gpl-3.0, GNU General Public License 3.0)
13  * 
14  **************************************************************************************************/
15 module fast.intmath;
16 
17 import fast.internal.helpers;
18 import fast.internal.sysdef;
19 
20 
21 version (LDC)
22 {
23 	@safe @nogc pure nothrow
24 	ulong mulu(ulong x, ulong y, ref bool overflow)
25 	{
26 		import ldc.intrinsics;
27 		auto res = llvm_umul_with_overflow(x, y);
28 		overflow = res.overflow;
29 		return res.result;
30 	}
31 }
32 else static if (isPosix && isGDC && (isAMD64 || isX86))
33 {
34 	@nogc pure nothrow
35 	ulong mulu(ulong x, ulong y, ref bool overflow)
36 	{
37 		version (GNU)
38 		{
39 			ulong lo;
40 			version (X86) asm { "
41 					cmp $0, 4+%2
42 					je 1f
43 					cmp $0, 4%3
44 					je 1f
45 					movb $1, %1
46 					1:
47 					mov 4+%2, %%eax
48 					mull %3
49 					jno 2f
50 					movb $1, %1
51 					2:
52 					mov %%eax, %%ecx
53 					mov %2, %%eax
54 					mull 4%3
55 					jno 3f
56 					movb $1, %1
57 					3:
58 					add %%eax, %%ecx
59 					jno 4f
60 					movb $1, %1
61 					4:
62 					mov %2, %%eax
63 					mull %3
64 					add %%ecx, %%edx
65 					jnc 5f
66 					movb $1, %1
67 					5:
68 					" : "=&A" lo, "+*m" overflow : "m" x, "m" y : "ecx"; }
69 			else asm { "mul %3\njno 1f\nmovb $1, %1\n1:\n" : "=a" lo, "+*m" overflow : "a" x, "r" y : "rdx"; }
70 			return lo;
71 		}
72 	}
73 }
74 else
75 {
76 	// DMD is already faster than my ASM code above, no need to improve. Good job Walter et al.
77 	import core.checkedint;
78 	alias mulu = core.checkedint.mulu;
79 }