diff options
| author | LemonBoy <thatlemon@gmail.com> | 2020-01-15 16:46:58 +0100 |
|---|---|---|
| committer | LemonBoy <thatlemon@gmail.com> | 2020-01-15 17:50:51 +0100 |
| commit | 5d5345728a0bbcd397a7667148f0c87dd0d7d14d (patch) | |
| tree | 96660563c17540e9d58266b2b4e2a39d9b036f47 /lib/std | |
| parent | 109e5f8a5aad76b3cbe344a9e292eabbcc637f1b (diff) | |
| download | zig-5d5345728a0bbcd397a7667148f0c87dd0d7d14d.tar.gz zig-5d5345728a0bbcd397a7667148f0c87dd0d7d14d.zip | |
Fix div builtins to use the correct calling convention
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/special/compiler_rt/arm.zig | 99 |
1 files changed, 64 insertions, 35 deletions
diff --git a/lib/std/special/compiler_rt/arm.zig b/lib/std/special/compiler_rt/arm.zig index 62d302258a..da4b595483 100644 --- a/lib/std/special/compiler_rt/arm.zig +++ b/lib/std/special/compiler_rt/arm.zig @@ -42,46 +42,75 @@ pub fn __aeabi_unwind_cpp_pr2() callconv(.C) void { unreachable; } -pub fn __aeabi_uidivmod(n: u32, d: u32) callconv(.C) extern struct { - q: u32, - r: u32, -} { - @setRuntimeSafety(is_test); +// The following functions are wrapped in an asm block to ensure the required +// calling convention is always respected - var result: @TypeOf(__aeabi_uidivmod).ReturnType = undefined; - result.q = __udivmodsi4(n, d, &result.r); - return result; +pub fn __aeabi_uidivmod() callconv(.Naked) void { + // Divide r0 by r1; the quotient goes in r0, the remainder in r1 + asm volatile ( + \\ push {lr} + \\ sub sp, #4 + \\ mov r2, sp + \\ bl __udivmodsi4 + \\ ldr r1, [sp] + \\ add sp, #4 + \\ pop {pc} + : + : + : "memory" + ); + unreachable; } -pub fn __aeabi_uldivmod(n: u64, d: u64) callconv(.C) extern struct { - q: u64, - r: u64, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_uldivmod).ReturnType = undefined; - result.q = __udivmoddi4(n, d, &result.r); - return result; +pub fn __aeabi_uldivmod() callconv(.Naked) void { + // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 + asm volatile ( + \\ push {r4, lr} + \\ sub sp, #16 + \\ add r4, sp, #8 + \\ bl __udivmoddi4 + \\ ldr r3, [sp, #8] + \\ ldr r4, [sp, #12] + \\ add sp, #16 + \\ pop {r4, pc} + : + : + : "memory" + ); + unreachable; } -pub fn __aeabi_idivmod(n: i32, d: i32) callconv(.C) extern struct { - q: i32, - r: i32, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_idivmod).ReturnType = undefined; - result.q = __divmodsi4(n, d, &result.r); - return result; +pub fn __aeabi_idivmod() callconv(.Naked) void { + // Divide r0 by r1; the quotient goes in r0, the remainder in r1 + asm volatile ( + \\ push {lr} + \\ sub sp, #4 + \\ mov r2, sp + \\ bl __divmodsi4 + \\ ldr r1, [sp] + \\ add sp, #4 + \\ pop {pc} + : + : + : "memory" + ); + unreachable; } -pub fn __aeabi_ldivmod(n: i64, d: i64) callconv(.C) extern struct { - q: i64, - r: i64, -} { - @setRuntimeSafety(is_test); - - var result: @TypeOf(__aeabi_ldivmod).ReturnType = undefined; - result.q = __divmoddi4(n, d, &result.r); - return result; +pub fn __aeabi_ldivmod() callconv(.Naked) void { + // Divide r1:r0 by r3:r2; the quotient goes in r1:r0, the remainder in r3:r2 + asm volatile ( + \\ push {r4, lr} + \\ sub sp, #16 + \\ add r4, sp, #8 + \\ bl __divmoddi4 + \\ ldr r3, [sp, #8] + \\ ldr r4, [sp, #12] + \\ add sp, #16 + \\ pop {r4, pc} + : + : + : "memory" + ); + unreachable; } |
