//! The syscall interface is identical to the ARM one but we're facing an extra //! challenge: r7, the register where the syscall number is stored, may be //! reserved for the frame pointer. //! Save and restore r7 around the syscall without touching the stack pointer not //! to break the frame chain. const std = @import("../../std.zig"); const SYS = std.os.linux.SYS; const arm = @import("arm.zig"); pub const syscall_arg_t = arm.syscall_arg_t; pub fn syscall0( number: SYS, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r1}" (&buf), : .{ .memory = true }); } pub fn syscall1( number: SYS, arg1: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r1}" (&buf), [arg1] "{r0}" (arg1), : .{ .memory = true }); } pub fn syscall2( number: SYS, arg1: syscall_arg_t, arg2: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r2}" (&buf), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), : .{ .memory = true }); } pub fn syscall3( number: SYS, arg1: syscall_arg_t, arg2: syscall_arg_t, arg3: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r3}" (&buf), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3), : .{ .memory = true }); } pub fn syscall4( number: SYS, arg1: syscall_arg_t, arg2: syscall_arg_t, arg3: syscall_arg_t, arg4: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r4}" (&buf), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3), [arg4] "{r3}" (arg4), : .{ .memory = true }); } pub fn syscall5( number: SYS, arg1: syscall_arg_t, arg2: syscall_arg_t, arg3: syscall_arg_t, arg4: syscall_arg_t, arg5: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r5}" (&buf), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3), [arg4] "{r3}" (arg4), [arg5] "{r4}" (arg5), : .{ .memory = true }); } pub fn syscall6( number: SYS, arg1: syscall_arg_t, arg2: syscall_arg_t, arg3: syscall_arg_t, arg4: syscall_arg_t, arg5: syscall_arg_t, arg6: syscall_arg_t, ) u32 { var buf: [2]syscall_arg_t = .{ @intFromEnum(number), undefined }; return asm volatile ( \\ str r7, [%[tmp], #4] \\ ldr r7, [%[tmp]] \\ svc #0 \\ ldr r7, [%[tmp], #4] : [ret] "={r0}" (-> u32), : [tmp] "{r6}" (&buf), [arg1] "{r0}" (arg1), [arg2] "{r1}" (arg2), [arg3] "{r2}" (arg3), [arg4] "{r3}" (arg4), [arg5] "{r4}" (arg5), [arg6] "{r5}" (arg6), : .{ .memory = true }); } pub const clone = arm.clone; pub const restore = arm.restore; pub const restore_rt = arm.restore_rt;