authorgravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-13 22:25:04+12:00
committergravatar for marc@tiehu.isMarc Tiehuis <marc@tiehu.is> 2018-06-13 22:25:04+12:00
log911014051487e83177689893e57491b86e72589b
treeb0b8a46dbe24efc53349e3a49bc3b75d2201a03c
parent86adc1ef39ed12ebe9eb6d3b7cf8eea481dd060d

Add i128 compiler-rt div/mul support


6 files changed, 163 insertions(+), 0 deletions(-)

CMakeLists.txt+2
......@@ -556,6 +556,7 @@ set(ZIG_STD_FILES
556556 "special/compiler_rt/aulldiv.zig"
557557 "special/compiler_rt/aullrem.zig"
558558 "special/compiler_rt/comparetf2.zig"
559 "special/compiler_rt/divti3.zig"
559560 "special/compiler_rt/fixuint.zig"
560561 "special/compiler_rt/fixunsdfdi.zig"
561562 "special/compiler_rt/fixunsdfsi.zig"
......@@ -566,6 +567,7 @@ set(ZIG_STD_FILES
566567 "special/compiler_rt/fixunstfdi.zig"
567568 "special/compiler_rt/fixunstfsi.zig"
568569 "special/compiler_rt/fixunstfti.zig"
570 "special/compiler_rt/muloti4.zig"
569571 "special/compiler_rt/index.zig"
570572 "special/compiler_rt/udivmod.zig"
571573 "special/compiler_rt/udivmoddi4.zig"
std/special/compiler_rt/divti3.zig created+16
......@@ -0,0 +1,16 @@
1const udivmod = @import("udivmod.zig").udivmod;
2const builtin = @import("builtin");
3
4pub extern fn __divti3(a: i128, b: i128) i128 {
5 @setRuntimeSafety(builtin.is_test);
6
7 const s_a = a >> (i128.bit_count - 1);
8 const s_b = b >> (i128.bit_count - 1);
9
10 const an = (a ^ s_a) -% s_a;
11 const bn = (b ^ s_b) -% s_b;
12
13 const r = udivmod(u128, @bitCast(u128, an), @bitCast(u128, bn), null);
14 const s = s_a ^ s_b;
15 return (i128(r) ^ s) -% s;
16}
std/special/compiler_rt/divti3_test.zig created+21
......@@ -0,0 +1,21 @@
1const __divti3 = @import("divti3.zig").__divti3;
2const assert = @import("std").debug.assert;
3
4fn test__divti3(a: i128, b: i128, expected: i128) void {
5 const x = __divti3(a, b);
6 assert(x == expected);
7}
8
9test "divti3" {
10 test__divti3(0, 1, 0);
11 test__divti3(0, -1, 0);
12 test__divti3(2, 1, 2);
13 test__divti3(2, -1, -2);
14 test__divti3(-2, 1, -2);
15 test__divti3(-2, -1, 2);
16
17 test__divti3(@bitCast(i128, u128(0x8 << 124)), 1, @bitCast(i128, u128(0x8 << 124)));
18 test__divti3(@bitCast(i128, u128(0x8 << 124)), -1, @bitCast(i128, u128(0x8 << 124)));
19 test__divti3(@bitCast(i128, u128(0x8 << 124)), -2, @bitCast(i128, u128(0x4 << 124)));
20 test__divti3(@bitCast(i128, u128(0x8 << 124)), 2, @bitCast(i128, u128(0xc << 124)));
21}
std/special/compiler_rt/index.zig+3
......@@ -38,6 +38,9 @@ comptime {
3838 @export("__umoddi3", __umoddi3, linkage);
3939 @export("__udivmodsi4", __udivmodsi4, linkage);
4040
41 @export("__divti3", @import("divti3.zig").__divti3, linkage);
42 @export("__muloti4", @import("muloti4.zig").__muloti4, linkage);
43
4144 if (isArmArch()) {
4245 @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage);
4346 @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage);
std/special/compiler_rt/muloti4.zig created+45
......@@ -0,0 +1,45 @@
1const udivmod = @import("udivmod.zig").udivmod;
2const builtin = @import("builtin");
3
4pub extern fn __muloti4(a: i128, b: i128, overflow: *c_int) i128 {
5 @setRuntimeSafety(builtin.is_test);
6
7 const min = @bitCast(i128, u128(1 << (i128.bit_count - 1)));
8 const max = ~min;
9 overflow.* = 0;
10
11 const r = a *% b;
12 if (a == min) {
13 if (b != 0 and b != 1) {
14 overflow.* = 1;
15 }
16 return r;
17 }
18 if (b == min) {
19 if (a != 0 and a != 1) {
20 overflow.* = 1;
21 }
22 return r;
23 }
24
25 const sa = a >> (i128.bit_count - 1);
26 const abs_a = (a ^ sa) -% sa;
27 const sb = b >> (i128.bit_count - 1);
28 const abs_b = (b ^ sb) -% sb;
29
30 if (abs_a < 2 or abs_b < 2) {
31 return r;
32 }
33
34 if (sa == sb) {
35 if (abs_a > @divFloor(max, abs_b)) {
36 overflow.* = 1;
37 }
38 } else {
39 if (abs_a > @divFloor(min, -abs_b)) {
40 overflow.* = 1;
41 }
42 }
43
44 return r;
45}
std/special/compiler_rt/muloti4_test.zig created+76
......@@ -0,0 +1,76 @@
1const __muloti4 = @import("muloti4.zig").__muloti4;
2const assert = @import("std").debug.assert;
3
4fn test__muloti4(a: i128, b: i128, expected: i128, expected_overflow: c_int) void {
5 var overflow: c_int = undefined;
6 const x = __muloti4(a, b, &overflow);
7 assert(overflow == expected_overflow and (overflow != 0 or x == expected));
8}
9
10test "muloti4" {
11 test__muloti4(0, 0, 0, 0);
12 test__muloti4(0, 1, 0, 0);
13 test__muloti4(1, 0, 0, 0);
14 test__muloti4(0, 10, 0, 0);
15 test__muloti4(10, 0, 0, 0);
16
17 test__muloti4(0, 81985529216486895, 0, 0);
18 test__muloti4(81985529216486895, 0, 0, 0);
19
20 test__muloti4(0, -1, 0, 0);
21 test__muloti4(-1, 0, 0, 0);
22 test__muloti4(0, -10, 0, 0);
23 test__muloti4(-10, 0, 0, 0);
24 test__muloti4(0, -81985529216486895, 0, 0);
25 test__muloti4(-81985529216486895, 0, 0, 0);
26
27 test__muloti4(3037000499, 3037000499, 9223372030926249001, 0);
28 test__muloti4(-3037000499, 3037000499, -9223372030926249001, 0);
29 test__muloti4(3037000499, -3037000499, -9223372030926249001, 0);
30 test__muloti4(-3037000499, -3037000499, 9223372030926249001, 0);
31
32 test__muloti4(4398046511103, 2097152, 9223372036852678656, 0);
33 test__muloti4(-4398046511103, 2097152, -9223372036852678656, 0);
34 test__muloti4(4398046511103, -2097152, -9223372036852678656, 0);
35 test__muloti4(-4398046511103, -2097152, 9223372036852678656, 0);
36
37 test__muloti4(2097152, 4398046511103, 9223372036852678656, 0);
38 test__muloti4(-2097152, 4398046511103, -9223372036852678656, 0);
39 test__muloti4(2097152, -4398046511103, -9223372036852678656, 0);
40 test__muloti4(-2097152, -4398046511103, 9223372036852678656, 0);
41
42 test__muloti4(@bitCast(i128, u128(0x00000000000000B504F333F9DE5BE000)), @bitCast(i128, u128(0x000000000000000000B504F333F9DE5B)), @bitCast(i128, u128(0x7FFFFFFFFFFFF328DF915DA296E8A000)), 0);
43 test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
44 test__muloti4(-2, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
45
46 test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), -1, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0);
47 test__muloti4(-1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 0);
48 test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0, 0);
49 test__muloti4(0, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0, 0);
50 test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
51 test__muloti4(1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
52 test__muloti4(@bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
53 test__muloti4(2, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
54
55 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), -2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
56 test__muloti4(-2, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
57 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), -1, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
58 test__muloti4(-1, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
59 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 0, 0, 0);
60 test__muloti4(0, @bitCast(i128, u128(0x80000000000000000000000000000000)), 0, 0);
61 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 1, @bitCast(i128, u128(0x80000000000000000000000000000000)), 0);
62 test__muloti4(1, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 0);
63 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000000)), 2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
64 test__muloti4(2, @bitCast(i128, u128(0x80000000000000000000000000000000)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
65
66 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), -2, @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
67 test__muloti4(-2, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 1);
68 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), -1, @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
69 test__muloti4(-1, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)), 0);
70 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 0, 0, 0);
71 test__muloti4(0, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0, 0);
72 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 1, @bitCast(i128, u128(0x80000000000000000000000000000001)), 0);
73 test__muloti4(1, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000001)), 0);
74 test__muloti4(@bitCast(i128, u128(0x80000000000000000000000000000001)), 2, @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
75 test__muloti4(2, @bitCast(i128, u128(0x80000000000000000000000000000001)), @bitCast(i128, u128(0x80000000000000000000000000000000)), 1);
76}