aboutsummaryrefslogtreecommitdiff
path: root/lib/std
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2020-01-15 16:46:58 +0100
committerLemonBoy <thatlemon@gmail.com>2020-01-15 17:50:51 +0100
commit5d5345728a0bbcd397a7667148f0c87dd0d7d14d (patch)
tree96660563c17540e9d58266b2b4e2a39d9b036f47 /lib/std
parent109e5f8a5aad76b3cbe344a9e292eabbcc637f1b (diff)
downloadzig-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.zig99
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;
}