master
  1//! The syscall interface is identical to the ARM one but we're facing an extra
  2//! challenge: r7, the register where the syscall number is stored, may be
  3//! reserved for the frame pointer.
  4//! Save and restore r7 around the syscall without touching the stack pointer not
  5//! to break the frame chain.
  6const std = @import("../../std.zig");
  7const SYS = std.os.linux.SYS;
  8
  9pub fn syscall0(number: SYS) u32 {
 10    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 11    return asm volatile (
 12        \\ str r7, [%[tmp], #4]
 13        \\ ldr r7, [%[tmp]]
 14        \\ svc #0
 15        \\ ldr r7, [%[tmp], #4]
 16        : [ret] "={r0}" (-> u32),
 17        : [tmp] "{r1}" (&buf),
 18        : .{ .memory = true });
 19}
 20
 21pub fn syscall1(number: SYS, arg1: u32) u32 {
 22    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 23    return asm volatile (
 24        \\ str r7, [%[tmp], #4]
 25        \\ ldr r7, [%[tmp]]
 26        \\ svc #0
 27        \\ ldr r7, [%[tmp], #4]
 28        : [ret] "={r0}" (-> u32),
 29        : [tmp] "{r1}" (&buf),
 30          [arg1] "{r0}" (arg1),
 31        : .{ .memory = true });
 32}
 33
 34pub fn syscall2(number: SYS, arg1: u32, arg2: u32) u32 {
 35    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 36    return asm volatile (
 37        \\ str r7, [%[tmp], #4]
 38        \\ ldr r7, [%[tmp]]
 39        \\ svc #0
 40        \\ ldr r7, [%[tmp], #4]
 41        : [ret] "={r0}" (-> u32),
 42        : [tmp] "{r2}" (&buf),
 43          [arg1] "{r0}" (arg1),
 44          [arg2] "{r1}" (arg2),
 45        : .{ .memory = true });
 46}
 47
 48pub fn syscall3(number: SYS, arg1: u32, arg2: u32, arg3: u32) u32 {
 49    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 50    return asm volatile (
 51        \\ str r7, [%[tmp], #4]
 52        \\ ldr r7, [%[tmp]]
 53        \\ svc #0
 54        \\ ldr r7, [%[tmp], #4]
 55        : [ret] "={r0}" (-> u32),
 56        : [tmp] "{r3}" (&buf),
 57          [arg1] "{r0}" (arg1),
 58          [arg2] "{r1}" (arg2),
 59          [arg3] "{r2}" (arg3),
 60        : .{ .memory = true });
 61}
 62
 63pub fn syscall4(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32) u32 {
 64    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 65    return asm volatile (
 66        \\ str r7, [%[tmp], #4]
 67        \\ ldr r7, [%[tmp]]
 68        \\ svc #0
 69        \\ ldr r7, [%[tmp], #4]
 70        : [ret] "={r0}" (-> u32),
 71        : [tmp] "{r4}" (&buf),
 72          [arg1] "{r0}" (arg1),
 73          [arg2] "{r1}" (arg2),
 74          [arg3] "{r2}" (arg3),
 75          [arg4] "{r3}" (arg4),
 76        : .{ .memory = true });
 77}
 78
 79pub fn syscall5(number: SYS, arg1: u32, arg2: u32, arg3: u32, arg4: u32, arg5: u32) u32 {
 80    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
 81    return asm volatile (
 82        \\ str r7, [%[tmp], #4]
 83        \\ ldr r7, [%[tmp]]
 84        \\ svc #0
 85        \\ ldr r7, [%[tmp], #4]
 86        : [ret] "={r0}" (-> u32),
 87        : [tmp] "{r5}" (&buf),
 88          [arg1] "{r0}" (arg1),
 89          [arg2] "{r1}" (arg2),
 90          [arg3] "{r2}" (arg3),
 91          [arg4] "{r3}" (arg4),
 92          [arg5] "{r4}" (arg5),
 93        : .{ .memory = true });
 94}
 95
 96pub fn syscall6(
 97    number: SYS,
 98    arg1: u32,
 99    arg2: u32,
100    arg3: u32,
101    arg4: u32,
102    arg5: u32,
103    arg6: u32,
104) u32 {
105    var buf: [2]u32 = .{ @intFromEnum(number), undefined };
106    return asm volatile (
107        \\ str r7, [%[tmp], #4]
108        \\ ldr r7, [%[tmp]]
109        \\ svc #0
110        \\ ldr r7, [%[tmp], #4]
111        : [ret] "={r0}" (-> u32),
112        : [tmp] "{r6}" (&buf),
113          [arg1] "{r0}" (arg1),
114          [arg2] "{r1}" (arg2),
115          [arg3] "{r2}" (arg3),
116          [arg4] "{r3}" (arg4),
117          [arg5] "{r4}" (arg5),
118          [arg6] "{r5}" (arg6),
119        : .{ .memory = true });
120}
121
122pub const clone = @import("arm.zig").clone;
123
124pub fn restore() callconv(.naked) noreturn {
125    asm volatile (
126        \\ mov r7, %[number]
127        \\ svc #0
128        :
129        : [number] "I" (@intFromEnum(SYS.sigreturn)),
130    );
131}
132
133pub fn restore_rt() callconv(.naked) noreturn {
134    asm volatile (
135        \\ mov r7, %[number]
136        \\ svc #0
137        :
138        : [number] "I" (@intFromEnum(SYS.rt_sigreturn)),
139    );
140}