authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-04-29 18:54:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-04-29 18:54:21-04:00
logd2328ac71a927df3ce9b7cec09c90dbb04ec3018
treec9a70c664767e2d797f6a56e475aeb5e0940eeef
parent75d42ace31e8965a6bce04965dfc4a9a7b322b4f
parent4e241263ff0081a756d4d331f1e78e571342bea4
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #2372 from LemonBoy/aeabi_idiv

compiler-rt: Add __divsi3, __aeabi_idiv

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

std/special/compiler_rt.zig+81-1
...@@ -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);
104104
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);
109111
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 {
112114
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);
117122
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}
560565
566extern 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
561extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {574extern fn __udivmodsi4(a: u32, b: u32, rem: *u32) u32 {
562 @setRuntimeSafety(is_test);575 @setRuntimeSafety(is_test);
563576
...@@ -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}
568581
582extern 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
569extern fn __udivsi3(n: u32, d: u32) u32 {596extern fn __udivsi3(n: u32, d: u32) u32 {
570 @setRuntimeSafety(is_test);597 @setRuntimeSafety(is_test);
571598
...@@ -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
1324test "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
1344fn 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
1349test "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
1371fn 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}