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;
8const arm = @import("arm.zig");
9
10pub const syscall_arg_t = arm.syscall_arg_t;
11
12pub fn syscall0(
13 number: SYS,
14) u32 {
15 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
16 return asm volatile (
17 \\ str r7, [%[tmp], #4]
18 \\ ldr r7, [%[tmp]]
19 \\ svc #0
20 \\ ldr r7, [%[tmp], #4]
21 : [ret] "={r0}" (-> u32),
22 : [tmp] "{r1}" (&buf),
23 : .{ .memory = true });
24}
25
26pub fn syscall1(
27 number: SYS,
28 arg1: syscall_arg_t,
29) u32 {
30 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
31 return asm volatile (
32 \\ str r7, [%[tmp], #4]
33 \\ ldr r7, [%[tmp]]
34 \\ svc #0
35 \\ ldr r7, [%[tmp], #4]
36 : [ret] "={r0}" (-> u32),
37 : [tmp] "{r1}" (&buf),
38 [arg1] "{r0}" (arg1),
39 : .{ .memory = true });
40}
41
42pub fn syscall2(
43 number: SYS,
44 arg1: syscall_arg_t,
45 arg2: syscall_arg_t,
46) u32 {
47 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
48 return asm volatile (
49 \\ str r7, [%[tmp], #4]
50 \\ ldr r7, [%[tmp]]
51 \\ svc #0
52 \\ ldr r7, [%[tmp], #4]
53 : [ret] "={r0}" (-> u32),
54 : [tmp] "{r2}" (&buf),
55 [arg1] "{r0}" (arg1),
56 [arg2] "{r1}" (arg2),
57 : .{ .memory = true });
58}
59
60pub fn syscall3(
61 number: SYS,
62 arg1: syscall_arg_t,
63 arg2: syscall_arg_t,
64 arg3: syscall_arg_t,
65) u32 {
66 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
67 return asm volatile (
68 \\ str r7, [%[tmp], #4]
69 \\ ldr r7, [%[tmp]]
70 \\ svc #0
71 \\ ldr r7, [%[tmp], #4]
72 : [ret] "={r0}" (-> u32),
73 : [tmp] "{r3}" (&buf),
74 [arg1] "{r0}" (arg1),
75 [arg2] "{r1}" (arg2),
76 [arg3] "{r2}" (arg3),
77 : .{ .memory = true });
78}
79
80pub fn syscall4(
81 number: SYS,
82 arg1: syscall_arg_t,
83 arg2: syscall_arg_t,
84 arg3: syscall_arg_t,
85 arg4: syscall_arg_t,
86) u32 {
87 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
88 return asm volatile (
89 \\ str r7, [%[tmp], #4]
90 \\ ldr r7, [%[tmp]]
91 \\ svc #0
92 \\ ldr r7, [%[tmp], #4]
93 : [ret] "={r0}" (-> u32),
94 : [tmp] "{r4}" (&buf),
95 [arg1] "{r0}" (arg1),
96 [arg2] "{r1}" (arg2),
97 [arg3] "{r2}" (arg3),
98 [arg4] "{r3}" (arg4),
99 : .{ .memory = true });
100}
101
102pub fn syscall5(
103 number: SYS,
104 arg1: syscall_arg_t,
105 arg2: syscall_arg_t,
106 arg3: syscall_arg_t,
107 arg4: syscall_arg_t,
108 arg5: syscall_arg_t,
109) u32 {
110 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
111 return asm volatile (
112 \\ str r7, [%[tmp], #4]
113 \\ ldr r7, [%[tmp]]
114 \\ svc #0
115 \\ ldr r7, [%[tmp], #4]
116 : [ret] "={r0}" (-> u32),
117 : [tmp] "{r5}" (&buf),
118 [arg1] "{r0}" (arg1),
119 [arg2] "{r1}" (arg2),
120 [arg3] "{r2}" (arg3),
121 [arg4] "{r3}" (arg4),
122 [arg5] "{r4}" (arg5),
123 : .{ .memory = true });
124}
125
126pub fn syscall6(
127 number: SYS,
128 arg1: syscall_arg_t,
129 arg2: syscall_arg_t,
130 arg3: syscall_arg_t,
131 arg4: syscall_arg_t,
132 arg5: syscall_arg_t,
133 arg6: syscall_arg_t,
134) u32 {
135 var buf: [2]syscall_arg_t = .{ @backingInt(number), undefined };
136 return asm volatile (
137 \\ str r7, [%[tmp], #4]
138 \\ ldr r7, [%[tmp]]
139 \\ svc #0
140 \\ ldr r7, [%[tmp], #4]
141 : [ret] "={r0}" (-> u32),
142 : [tmp] "{r6}" (&buf),
143 [arg1] "{r0}" (arg1),
144 [arg2] "{r1}" (arg2),
145 [arg3] "{r2}" (arg3),
146 [arg4] "{r3}" (arg4),
147 [arg5] "{r4}" (arg5),
148 [arg6] "{r5}" (arg6),
149 : .{ .memory = true });
150}
151
152pub const clone = arm.clone;
153
154pub const restore = arm.restore;
155
156pub const restore_rt = arm.restore_rt;