| ... | @@ -102,9 +102,11 @@ comptime { | ... | @@ -102,9 +102,11 @@ 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); |
| | 109 | @export("__divmodsi4", __divmodsi4, linkage); |
| 108 | @export("__udivmodsi4", __udivmodsi4, linkage); | 110 | @export("__udivmodsi4", __udivmodsi4, linkage); |
| 109 | | 111 | |
| 110 | @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage); | 112 | @export("__negsf2", @import("compiler_rt/negXf2.zig").__negsf2, linkage); |
| ... | @@ -112,8 +114,11 @@ comptime { | ... | @@ -112,8 +114,11 @@ comptime { |
| 112 | | 114 | |
| 113 | if (is_arm_arch and !is_arm_64) { | 115 | if (is_arm_arch and !is_arm_64) { |
| 114 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); | 116 | @export("__aeabi_uldivmod", __aeabi_uldivmod, linkage); |
| 115 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); | 117 | |
| | 118 | @export("__aeabi_idiv", __divsi3, linkage); |
| | 119 | @export("__aeabi_idivmod", __divmodsi4, linkage); |
| 116 | @export("__aeabi_uidiv", __udivsi3, linkage); | 120 | @export("__aeabi_uidiv", __udivsi3, linkage); |
| | 121 | @export("__aeabi_uidivmod", __aeabi_uidivmod, linkage); |
| 117 | | 122 | |
| 118 | @export("__aeabi_memcpy", __aeabi_memcpy, linkage); | 123 | @export("__aeabi_memcpy", __aeabi_memcpy, linkage); |
| 119 | @export("__aeabi_memcpy4", __aeabi_memcpy, linkage); | 124 | @export("__aeabi_memcpy4", __aeabi_memcpy, linkage); |
| ... | @@ -558,6 +563,14 @@ nakedcc fn ___chkstk_ms() align(4) void { | ... | @@ -558,6 +563,14 @@ nakedcc fn ___chkstk_ms() align(4) void { |
| 558 | ); | 563 | ); |
| 559 | } | 564 | } |
| 560 | | 565 | |
| | 566 | extern fn __divmodsi4(a: i32, b: i32, rem: *i32) i32 { |
| | 567 | @setRuntimeSafety(is_test); |
| | 568 | |
| | 569 | const d = __divsi3(a, b); |
| | 570 | rem.* = a -% (d * b); |
| | 571 | return d; |
| | 572 | } |
| | 573 | |
| 561 | extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { | 574 | extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { |
| 562 | @setRuntimeSafety(is_test); | 575 | @setRuntimeSafety(is_test); |
| 563 | | 576 | |
| ... | @@ -566,6 +579,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { | ... | @@ -566,6 +579,20 @@ extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 { |
| 566 | return d; | 579 | return d; |
| 567 | } | 580 | } |
| 568 | | 581 | |
| | 582 | extern fn __divsi3(n: i32, d: i32) i32 { |
| | 583 | @setRuntimeSafety(is_test); |
| | 584 | |
| | 585 | // Set aside the sign of the quotient. |
| | 586 | const sign = @bitCast(u32, (n ^ d) >> 31); |
| | 587 | // Take absolute value of a and b via abs(x) = (x^(x >> 31)) - (x >> 31). |
| | 588 | const abs_n = (n ^ (n >> 31)) -% (n >> 31); |
| | 589 | const abs_d = (d ^ (d >> 31)) -% (d >> 31); |
| | 590 | // abs(a) / abs(b) |
| | 591 | const res = @bitCast(u32, abs_n) / @bitCast(u32, abs_d); |
| | 592 | // Apply sign of quotient to result and return. |
| | 593 | return @bitCast(i32, (res ^ sign) -% sign); |
| | 594 | } |
| | 595 | |
| 569 | extern fn __udivsi3(n: u32, d: u32) u32 { | 596 | extern fn __udivsi3(n: u32, d: u32) u32 { |
| 570 | @setRuntimeSafety(is_test); | 597 | @setRuntimeSafety(is_test); |
| 571 | | 598 | |
| ... | @@ -1293,3 +1320,56 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { | ... | @@ -1293,3 +1320,56 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) void { |
| 1293 | const q: u32 = __udivsi3(a, b); | 1320 | const q: u32 = __udivsi3(a, b); |
| 1294 | testing.expect(q == expected_q); | 1321 | testing.expect(q == expected_q); |
| 1295 | } | 1322 | } |
| | 1323 | |
| | 1324 | test "test_divsi3" { |
| | 1325 | const cases = [][3]i32{ |
| | 1326 | []i32{ 0, 1, 0}, |
| | 1327 | []i32{ 0, -1, 0}, |
| | 1328 | []i32{ 2, 1, 2}, |
| | 1329 | []i32{ 2, -1, -2}, |
| | 1330 | []i32{-2, 1, -2}, |
| | 1331 | []i32{-2, -1, 2}, |
| | 1332 | |
| | 1333 | []i32{@bitCast(i32, u32(0x80000000)), 1, @bitCast(i32, u32(0x80000000))}, |
| | 1334 | []i32{@bitCast(i32, u32(0x80000000)), -1, @bitCast(i32, u32(0x80000000))}, |
| | 1335 | []i32{@bitCast(i32, u32(0x80000000)), -2, 0x40000000}, |
| | 1336 | []i32{@bitCast(i32, u32(0x80000000)), 2, @bitCast(i32, u32(0xC0000000))}, |
| | 1337 | }; |
| | 1338 | |
| | 1339 | for (cases) |case| { |
| | 1340 | test_one_divsi3(case[0], case[1], case[2]); |
| | 1341 | } |
| | 1342 | } |
| | 1343 | |
| | 1344 | fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void { |
| | 1345 | const q: i32 = __divsi3(a, b); |
| | 1346 | testing.expect(q == expected_q); |
| | 1347 | } |
| | 1348 | |
| | 1349 | test "test_divmodsi4" { |
| | 1350 | const cases = [][4]i32{ |
| | 1351 | []i32{ 0, 1, 0, 0}, |
| | 1352 | []i32{ 0, -1, 0, 0}, |
| | 1353 | []i32{ 2, 1, 2, 0}, |
| | 1354 | []i32{ 2, -1, -2, 0}, |
| | 1355 | []i32{-2, 1, -2, 0}, |
| | 1356 | []i32{-2, -1, 2, 0}, |
| | 1357 | []i32{ 7, 5, 1, 2}, |
| | 1358 | []i32{-7, 5, -1, -2}, |
| | 1359 | []i32{19, 5, 3, 4}, |
| | 1360 | []i32{19, -5, -3, 4}, |
| | 1361 | |
| | 1362 | []i32{@bitCast(i32, u32(0x80000000)), 8, @bitCast(i32, u32(0xf0000000)), 0}, |
| | 1363 | []i32{@bitCast(i32, u32(0x80000007)), 8, @bitCast(i32, u32(0xf0000001)), -1}, |
| | 1364 | }; |
| | 1365 | |
| | 1366 | for (cases) |case| { |
| | 1367 | test_one_divmodsi4(case[0], case[1], case[2], case[3]); |
| | 1368 | } |
| | 1369 | } |
| | 1370 | |
| | 1371 | fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) void { |
| | 1372 | var r: i32 = undefined; |
| | 1373 | const q: i32 = __divmodsi4(a, b, &r); |
| | 1374 | testing.expect(q == expected_q and r == expected_r); |
| | 1375 | } |