| ... | @@ -102,6 +102,7 @@ comptime { | ... | @@ -102,6 +102,7 @@ comptime { |
| 102 | @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage); | 102 | @export("__udivmoddi4", @import("compiler_rt/udivmoddi4.zig").__udivmoddi4, linkage); |
| 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("__udivsi3", __udivsi3, linkage); | 106 | @export("__udivsi3", __udivsi3, linkage); |
| 106 | @export("__udivdi3", __udivdi3, linkage); | 107 | @export("__udivdi3", __udivdi3, linkage); |
| 107 | @export("__umoddi3", __umoddi3, linkage); | 108 | @export("__umoddi3", __umoddi3, linkage); |
| ... | @@ -113,6 +114,8 @@ comptime { | ... | @@ -113,6 +114,8 @@ comptime { |
| 113 | if (is_arm_arch and !is_arm_64) { | 114 | if (is_arm_arch and !is_arm_64) { |
| 114 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); | 115 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); |
| 115 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); | 116 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); |
| | 117 | |
| | 118 | @export("__aeabi_idiv", __divsi3, linkage); |
| 116 | @export("__aeabi_uidiv", __udivsi3, linkage); | 119 | @export("__aeabi_uidiv", __udivsi3, linkage); |
| 117 | | 120 | |
| 118 | @export("__aeabi_memcpy", __aeabi_memcpy, linkage); | 121 | @export("__aeabi_memcpy", __aeabi_memcpy, linkage); |
| ... | @@ -566,6 +569,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { | ... | @@ -566,6 +569,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { |
| 566 | return d; | 569 | return d; |
| 567 | } | 570 | } |
| 568 | | 571 | |
| | 572 | extern fn __divsi3(n: i32, d: i32) i32 { |
| | 573 | @setRuntimeSafety(is_test); |
| | 574 | |
| | 575 | // Set aside the sign of the quotient. |
| | 576 | const sign = @bitCast(u32, (n ^ d) >> 31); |
| | 577 | // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). |
| | 578 | const abs_n = (n ^ (n >> 31)) -% (n >> 31); |
| | 579 | const abs_d = (d ^ (d >> 31)) -% (d >> 31); |
| | 580 | // abs(a) / abs(b) |
| | 581 | const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d); |
| | 582 | // Apply sign of quotient to result and return. |
| | 583 | return @bitCast(i32, (res ^ sign) -% sign); |
| | 584 | } |
| | 585 | |
| 569 | extern fn __udivsi3(n: u32, d: u32) u32 { | 586 | extern fn __udivsi3(n: u32, d: u32) u32 { |
| 570 | @setRuntimeSafety(is_test); | 587 | @setRuntimeSafety(is_test); |
| 571 | | 588 | |
| ... | @@ -1293,3 +1310,28 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { | ... | @@ -1293,3 +1310,28 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { |
| 1293 | const q: u32 = __udivsi3(a, b); | 1310 | const q: u32 = __udivsi3(a, b); |
| 1294 | testing.expect(q == expected_q); | 1311 | testing.expect(q == expected_q); |
| 1295 | } | 1312 | } |
| | 1313 | |
| | 1314 | test "test_divsi3" { |
| | 1315 | const cases = [][3]i32{ |
| | 1316 | []i32{ 0, 1, 0}, |
| | 1317 | []i32{ 0, -1, 0}, |
| | 1318 | []i32{ 2, 1, 2}, |
| | 1319 | []i32{ 2, -1, -2}, |
| | 1320 | []i32{-2, 1, -2}, |
| | 1321 | []i32{-2, -1, 2}, |
| | 1322 | |
| | 1323 | []i32{@bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000))}, |
| | 1324 | []i32{@bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000))}, |
| | 1325 | []i32{@bitCast(i32, u32(0x80000000)), -2, 0x40000000}, |
| | 1326 | []i32{@bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000))}, |
| | 1327 | }; |
| | 1328 | |
| | 1329 | for (cases) |case| { |
| | 1330 | test_one_divsi3(case[0], case[1], case[2]); |
| | 1331 | } |
| | 1332 | } |
| | 1333 | |
| | 1334 | fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void { |
| | 1335 | const q: i32 = __divsi3(a, b); |
| | 1336 | testing.expect(q == expected_q); |
| | 1337 | } |