authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-05-03 09:41:46+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-03 17:12:33-04:00
log1be4e87f0bfffa07bc150ff8057aef3a9e85144c
tree13b29f3aa2f7181f6736bad5f62a38b681a99049
parent584dd2863a23243c5d587358d0f06b631a5f9575

compiler-rt: Add __moddi3, __divdi3


1 files changed, 81 insertions(+), 0 deletions(-)

std/special/compiler_rt.zig+81
...@@ -103,8 +103,10 @@ comptime {...@@ -103,8 +103,10 @@ comptime {
103 @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);103 @export("__popcountdi2", @import("compiler_rt/popcountdi2.zig").__popcountdi2, linkage);
104104
105 @export("__divsi3", __divsi3, linkage);105 @export("__divsi3", __divsi3, linkage);
106 @export("__divdi3", __divdi3, linkage);
106 @export("__udivsi3", __udivsi3, linkage);107 @export("__udivsi3", __udivsi3, linkage);
107 @export("__udivdi3", __udivdi3, linkage);108 @export("__udivdi3", __udivdi3, linkage);
109 @export("__moddi3", __moddi3, linkage);
108 @export("__umoddi3", __umoddi3, linkage);110 @export("__umoddi3", __umoddi3, linkage);
109 @export("__divmodsi4", __divmodsi4, linkage);111 @export("__divmodsi4", __divmodsi4, linkage);
110 @export("__udivmodsi4", __udivmodsi4, linkage);112 @export("__udivmodsi4", __udivmodsi4, linkage);
...@@ -241,6 +243,33 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn...@@ -241,6 +243,33 @@ pub fn panic(msg: []const u8, error_return_trace: ?*builtin.StackTrace) noreturn
241 }243 }
242}244}
243245
246extern fn __divdi3(a: i64, b: i64) i64 {
247 @setRuntimeSafety(is_test);
248
249 // Set aside the sign of the quotient.
250 const sign = @bitCast(u64, (a ^ b) >> 63);
251 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
252 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
253 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
254 // Unsigned division
255 const res = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), null);
256 // Apply sign of quotient to result and return.
257 return @bitCast(i64, (res ^ sign) -% sign);
258}
259
260extern fn __moddi3(a: i64, b: i64) i64 {
261 @setRuntimeSafety(is_test);
262
263 // Take absolute value of a and b via abs(x) = (x^(x >> 63)) - (x >> 63).
264 const abs_a = (a ^ (a >> 63)) -% (a >> 63);
265 const abs_b = (b ^ (b >> 63)) -% (b >> 63);
266 // Unsigned division
267 var r: u64 = undefined;
268 _ = __udivmoddi4(@bitCast(u64, abs_a), @bitCast(u64, abs_b), &r);
269 // Apply the sign of the dividend and return.
270 return (@bitCast(i64, r) ^ (a >> 63)) -% (a >> 63);
271}
272
244extern fn __udivdi3(a: u64, b: u64) u64 {273extern fn __udivdi3(a: u64, b: u64) u64 {
245 @setRuntimeSafety(is_test);274 @setRuntimeSafety(is_test);
246 return __udivmoddi4(a, b, null);275 return __udivmoddi4(a, b, null);
...@@ -1374,3 +1403,55 @@ fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void {...@@ -1374,3 +1403,55 @@ fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void {
1374 const q: i32 = __divmodsi4(a, b, &r);1403 const q: i32 = __divmodsi4(a, b, &r);
1375 testing.expect(q == expected_q and r == expected_r);1404 testing.expect(q == expected_q and r == expected_r);
1376}1405}
1406
1407test "test_divdi3" {
1408 const cases = [][3]i64{
1409 []i64{ 0, 1, 0},
1410 []i64{ 0, -1, 0},
1411 []i64{ 2, 1, 2},
1412 []i64{ 2, -1, -2},
1413 []i64{-2, 1, -2},
1414 []i64{-2, -1, 2},
1415
1416 []i64{@bitCast(i64, u64(0x8000000000000000)), 1, @bitCast(i64, u64(0x8000000000000000))},
1417 []i64{@bitCast(i64, u64(0x8000000000000000)), -1, @bitCast(i64, u64(0x8000000000000000))},
1418 []i64{@bitCast(i64, u64(0x8000000000000000)), -2, 0x4000000000000000},
1419 []i64{@bitCast(i64, u64(0x8000000000000000)), 2, @bitCast(i64, u64(0xC000000000000000))},
1420 };
1421
1422 for (cases) |case| {
1423 test_one_divdi3(case[0], case[1], case[2]);
1424 }
1425}
1426
1427fn test_one_divdi3(a: i64, b: i64, expected_q: i64) void {
1428 const q: i64 = __divdi3(a, b);
1429 testing.expect(q == expected_q);
1430}
1431
1432test "test_moddi3" {
1433 const cases = [][3]i64{
1434 []i64{0, 1, 0},
1435 []i64{0, -1, 0},
1436 []i64{5, 3, 2},
1437 []i64{5, -3, 2},
1438 []i64{-5, 3, -2},
1439 []i64{-5, -3, -2},
1440
1441 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), 1, 0},
1442 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), -1, 0},
1443 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), 2, 0},
1444 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), -2, 0},
1445 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), 3, -2},
1446 []i64{@bitCast(i64, @intCast(u64, 0x8000000000000000)), -3, -2},
1447 };
1448
1449 for (cases) |case| {
1450 test_one_moddi3(case[0], case[1], case[2]);
1451 }
1452}
1453
1454fn test_one_moddi3(a: i64, b: i64, expected_r: i64) void {
1455 const r: i64 = __moddi3(a, b);
1456 testing.expect(r == expected_r);
1457}