| ... | @@ -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); |
| 104 | | 104 | |
| 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 | } |
| 243 | | 245 | |
| | 246 | extern 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 | |
| | 260 | extern 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 | |
| 244 | extern fn __udivdi3(a: u64, b: u64) u64 { | 273 | extern 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 | |
| | 1407 | test "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 | |
| | 1427 | fn 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 | |
| | 1432 | test "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 | |
| | 1454 | fn 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 | } |