1 //! arm Linux system calls, using thumb-mode. 2 //! 3 //! In thumb-mode, r7 is the frame pointer and is not permitted to be used in 4 //! an inline asm operand, so we have to use a different register and copy it 5 //! into r7 inside the inline asm. 6 7 use crate::backend::reg::{ 8 ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0, 9 }; 10 use core::arch::asm; 11 12 #[inline] 13 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber<'_>) -> RetReg<R0> { 14 let r0; 15 asm!( 16 "mov {tmp}, r7", 17 "mov r7, {nr}", 18 "svc 0", 19 "mov r7, {tmp}", 20 nr = in(reg) nr.to_asm(), 21 tmp = out(reg) _, 22 lateout("r0") r0, 23 options(nostack, preserves_flags, readonly) 24 ); 25 FromAsm::from_asm(r0) 26 } 27 28 #[inline] 29 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> { 30 let r0; 31 asm!( 32 "mov {tmp}, r7", 33 "mov r7, {nr}", 34 "svc 0", 35 "mov r7, {tmp}", 36 nr = in(reg) nr.to_asm(), 37 tmp = out(reg) _, 38 inlateout("r0") a0.to_asm() => r0, 39 options(nostack, preserves_flags) 40 ); 41 FromAsm::from_asm(r0) 42 } 43 44 #[inline] 45 pub(in crate::backend) unsafe fn syscall1_readonly( 46 nr: SyscallNumber<'_>, 47 a0: ArgReg<'_, A0>, 48 ) -> RetReg<R0> { 49 let r0; 50 asm!( 51 "mov {tmp}, r7", 52 "mov r7, {nr}", 53 "svc 0", 54 "mov r7, {tmp}", 55 nr = in(reg) nr.to_asm(), 56 tmp = out(reg) _, 57 inlateout("r0") a0.to_asm() => r0, 58 options(nostack, preserves_flags, readonly) 59 ); 60 FromAsm::from_asm(r0) 61 } 62 63 #[inline] 64 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! { 65 asm!( 66 "mov r7, {nr}", 67 "svc 0", 68 nr = in(reg) nr.to_asm(), 69 in("r0") a0.to_asm(), 70 options(noreturn) 71 ) 72 } 73 74 #[inline] 75 pub(in crate::backend) unsafe fn syscall2( 76 nr: SyscallNumber<'_>, 77 a0: ArgReg<'_, A0>, 78 a1: ArgReg<'_, A1>, 79 ) -> RetReg<R0> { 80 let r0; 81 asm!( 82 "mov {tmp}, r7", 83 "mov r7, {nr}", 84 "svc 0", 85 "mov r7, {tmp}", 86 nr = in(reg) nr.to_asm(), 87 tmp = out(reg) _, 88 inlateout("r0") a0.to_asm() => r0, 89 in("r1") a1.to_asm(), 90 options(nostack, preserves_flags) 91 ); 92 FromAsm::from_asm(r0) 93 } 94 95 #[inline] 96 pub(in crate::backend) unsafe fn syscall2_readonly( 97 nr: SyscallNumber<'_>, 98 a0: ArgReg<'_, A0>, 99 a1: ArgReg<'_, A1>, 100 ) -> RetReg<R0> { 101 let r0; 102 asm!( 103 "mov {tmp}, r7", 104 "mov r7, {nr}", 105 "svc 0", 106 "mov r7, {tmp}", 107 nr = in(reg) nr.to_asm(), 108 tmp = out(reg) _, 109 inlateout("r0") a0.to_asm() => r0, 110 in("r1") a1.to_asm(), 111 options(nostack, preserves_flags, readonly) 112 ); 113 FromAsm::from_asm(r0) 114 } 115 116 #[inline] 117 pub(in crate::backend) unsafe fn syscall3( 118 nr: SyscallNumber<'_>, 119 a0: ArgReg<'_, A0>, 120 a1: ArgReg<'_, A1>, 121 a2: ArgReg<'_, A2>, 122 ) -> RetReg<R0> { 123 let r0; 124 asm!( 125 "mov {tmp}, r7", 126 "mov r7, {nr}", 127 "svc 0", 128 "mov r7, {tmp}", 129 nr = in(reg) nr.to_asm(), 130 tmp = out(reg) _, 131 inlateout("r0") a0.to_asm() => r0, 132 in("r1") a1.to_asm(), 133 in("r2") a2.to_asm(), 134 options(nostack, preserves_flags) 135 ); 136 FromAsm::from_asm(r0) 137 } 138 139 #[inline] 140 pub(in crate::backend) unsafe fn syscall3_readonly( 141 nr: SyscallNumber<'_>, 142 a0: ArgReg<'_, A0>, 143 a1: ArgReg<'_, A1>, 144 a2: ArgReg<'_, A2>, 145 ) -> RetReg<R0> { 146 let r0; 147 asm!( 148 "mov {tmp}, r7", 149 "mov r7, {nr}", 150 "svc 0", 151 "mov r7, {tmp}", 152 nr = in(reg) nr.to_asm(), 153 tmp = out(reg) _, 154 inlateout("r0") a0.to_asm() => r0, 155 in("r1") a1.to_asm(), 156 in("r2") a2.to_asm(), 157 options(nostack, preserves_flags, readonly) 158 ); 159 FromAsm::from_asm(r0) 160 } 161 162 #[inline] 163 pub(in crate::backend) unsafe fn syscall4( 164 nr: SyscallNumber<'_>, 165 a0: ArgReg<'_, A0>, 166 a1: ArgReg<'_, A1>, 167 a2: ArgReg<'_, A2>, 168 a3: ArgReg<'_, A3>, 169 ) -> RetReg<R0> { 170 let r0; 171 asm!( 172 "mov {tmp}, r7", 173 "mov r7, {nr}", 174 "svc 0", 175 "mov r7, {tmp}", 176 nr = in(reg) nr.to_asm(), 177 tmp = out(reg) _, 178 inlateout("r0") a0.to_asm() => r0, 179 in("r1") a1.to_asm(), 180 in("r2") a2.to_asm(), 181 in("r3") a3.to_asm(), 182 options(nostack, preserves_flags) 183 ); 184 FromAsm::from_asm(r0) 185 } 186 187 #[inline] 188 pub(in crate::backend) unsafe fn syscall4_readonly( 189 nr: SyscallNumber<'_>, 190 a0: ArgReg<'_, A0>, 191 a1: ArgReg<'_, A1>, 192 a2: ArgReg<'_, A2>, 193 a3: ArgReg<'_, A3>, 194 ) -> RetReg<R0> { 195 let r0; 196 asm!( 197 "mov {tmp}, r7", 198 "mov r7, {nr}", 199 "svc 0", 200 "mov r7, {tmp}", 201 nr = in(reg) nr.to_asm(), 202 tmp = out(reg) _, 203 inlateout("r0") a0.to_asm() => r0, 204 in("r1") a1.to_asm(), 205 in("r2") a2.to_asm(), 206 in("r3") a3.to_asm(), 207 options(nostack, preserves_flags, readonly) 208 ); 209 FromAsm::from_asm(r0) 210 } 211 212 #[inline] 213 pub(in crate::backend) unsafe fn syscall5( 214 nr: SyscallNumber<'_>, 215 a0: ArgReg<'_, A0>, 216 a1: ArgReg<'_, A1>, 217 a2: ArgReg<'_, A2>, 218 a3: ArgReg<'_, A3>, 219 a4: ArgReg<'_, A4>, 220 ) -> RetReg<R0> { 221 let r0; 222 asm!( 223 "mov {tmp}, r7", 224 "mov r7, {nr}", 225 "svc 0", 226 "mov r7, {tmp}", 227 nr = in(reg) nr.to_asm(), 228 tmp = out(reg) _, 229 inlateout("r0") a0.to_asm() => r0, 230 in("r1") a1.to_asm(), 231 in("r2") a2.to_asm(), 232 in("r3") a3.to_asm(), 233 in("r4") a4.to_asm(), 234 options(nostack, preserves_flags) 235 ); 236 FromAsm::from_asm(r0) 237 } 238 239 #[inline] 240 pub(in crate::backend) unsafe fn syscall5_readonly( 241 nr: SyscallNumber<'_>, 242 a0: ArgReg<'_, A0>, 243 a1: ArgReg<'_, A1>, 244 a2: ArgReg<'_, A2>, 245 a3: ArgReg<'_, A3>, 246 a4: ArgReg<'_, A4>, 247 ) -> RetReg<R0> { 248 let r0; 249 asm!( 250 "mov {tmp}, r7", 251 "mov r7, {nr}", 252 "svc 0", 253 "mov r7, {tmp}", 254 nr = in(reg) nr.to_asm(), 255 tmp = out(reg) _, 256 inlateout("r0") a0.to_asm() => r0, 257 in("r1") a1.to_asm(), 258 in("r2") a2.to_asm(), 259 in("r3") a3.to_asm(), 260 in("r4") a4.to_asm(), 261 options(nostack, preserves_flags, readonly) 262 ); 263 FromAsm::from_asm(r0) 264 } 265 266 #[inline] 267 pub(in crate::backend) unsafe fn syscall6( 268 nr: SyscallNumber<'_>, 269 a0: ArgReg<'_, A0>, 270 a1: ArgReg<'_, A1>, 271 a2: ArgReg<'_, A2>, 272 a3: ArgReg<'_, A3>, 273 a4: ArgReg<'_, A4>, 274 a5: ArgReg<'_, A5>, 275 ) -> RetReg<R0> { 276 let r0; 277 asm!( 278 "mov {tmp}, r7", 279 "mov r7, {nr}", 280 "svc 0", 281 "mov r7, {tmp}", 282 nr = in(reg) nr.to_asm(), 283 tmp = out(reg) _, 284 inlateout("r0") a0.to_asm() => r0, 285 in("r1") a1.to_asm(), 286 in("r2") a2.to_asm(), 287 in("r3") a3.to_asm(), 288 in("r4") a4.to_asm(), 289 in("r5") a5.to_asm(), 290 options(nostack, preserves_flags) 291 ); 292 FromAsm::from_asm(r0) 293 } 294 295 #[inline] 296 pub(in crate::backend) unsafe fn syscall6_readonly( 297 nr: SyscallNumber<'_>, 298 a0: ArgReg<'_, A0>, 299 a1: ArgReg<'_, A1>, 300 a2: ArgReg<'_, A2>, 301 a3: ArgReg<'_, A3>, 302 a4: ArgReg<'_, A4>, 303 a5: ArgReg<'_, A5>, 304 ) -> RetReg<R0> { 305 let r0; 306 asm!( 307 "mov {tmp}, r7", 308 "mov r7, {nr}", 309 "svc 0", 310 "mov r7, {tmp}", 311 nr = in(reg) nr.to_asm(), 312 tmp = out(reg) _, 313 inlateout("r0") a0.to_asm() => r0, 314 in("r1") a1.to_asm(), 315 in("r2") a2.to_asm(), 316 in("r3") a3.to_asm(), 317 in("r4") a4.to_asm(), 318 in("r5") a5.to_asm(), 319 options(nostack, preserves_flags, readonly) 320 ); 321 FromAsm::from_asm(r0) 322 } 323