1 //! mips64el Linux system calls. 2 //! 3 //! On mips64el, Linux indicates success or failure using `$a3` (`$7`) rather 4 //! than by returning a negative error code as most other architectures do. 5 //! 6 //! Mips-family platforms have a special calling convention for `__NR_pipe`, 7 //! however we use `__NR_pipe2` instead to avoid having to implement it. 8 9 use crate::backend::reg::{ 10 ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0, 11 }; 12 use core::arch::asm; 13 14 #[inline] 15 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> { 16 let x0; 17 let err: usize; 18 asm!( 19 "syscall", 20 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 21 lateout("$7" /*$a3*/) err, 22 lateout("$8" /*$a4*/) _, 23 lateout("$9" /*$a5*/) _, 24 lateout("$10" /*$a6*/) _, 25 lateout("$11" /*$a7*/) _, 26 lateout("$12" /*$t0*/) _, 27 lateout("$13" /*$t1*/) _, 28 lateout("$14" /*$t2*/) _, 29 lateout("$15" /*$t3*/) _, 30 lateout("$24" /*$t8*/) _, 31 lateout("$25" /*$t9*/) _, 32 options(nostack, preserves_flags, readonly) 33 ); 34 FromAsm::from_asm(if err != 0 { 35 (x0 as usize).wrapping_neg() as *mut _ 36 } else { 37 x0 38 }) 39 } 40 41 #[inline] 42 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> { 43 let x0; 44 let err: usize; 45 asm!( 46 "syscall", 47 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 48 in("$4" /*$a0*/) a0.to_asm(), 49 lateout("$7" /*$a3*/) err, 50 lateout("$8" /*$a4*/) _, 51 lateout("$9" /*$a5*/) _, 52 lateout("$10" /*$a6*/) _, 53 lateout("$11" /*$a7*/) _, 54 lateout("$12" /*$t0*/) _, 55 lateout("$13" /*$t1*/) _, 56 lateout("$14" /*$t2*/) _, 57 lateout("$15" /*$t3*/) _, 58 lateout("$24" /*$t8*/) _, 59 lateout("$25" /*$t9*/) _, 60 options(nostack, preserves_flags) 61 ); 62 FromAsm::from_asm(if err != 0 { 63 (x0 as usize).wrapping_neg() as *mut _ 64 } else { 65 x0 66 }) 67 } 68 69 #[inline] 70 pub(in crate::backend) unsafe fn syscall1_readonly( 71 nr: SyscallNumber<'_>, 72 a0: ArgReg<'_, A0>, 73 ) -> RetReg<R0> { 74 let x0; 75 let err: usize; 76 asm!( 77 "syscall", 78 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 79 in("$4" /*$a0*/) a0.to_asm(), 80 lateout("$7" /*$a3*/) err, 81 lateout("$8" /*$a4*/) _, 82 lateout("$9" /*$a5*/) _, 83 lateout("$10" /*$a6*/) _, 84 lateout("$11" /*$a7*/) _, 85 lateout("$12" /*$t0*/) _, 86 lateout("$13" /*$t1*/) _, 87 lateout("$14" /*$t2*/) _, 88 lateout("$15" /*$t3*/) _, 89 lateout("$24" /*$t8*/) _, 90 lateout("$25" /*$t9*/) _, 91 options(nostack, preserves_flags, readonly) 92 ); 93 FromAsm::from_asm(if err != 0 { 94 (x0 as usize).wrapping_neg() as *mut _ 95 } else { 96 x0 97 }) 98 } 99 100 #[inline] 101 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! { 102 asm!( 103 "syscall", 104 in("$2" /*$v0*/) nr.to_asm(), 105 in("$4" /*$a0*/) a0.to_asm(), 106 options(noreturn) 107 ) 108 } 109 110 #[inline] 111 pub(in crate::backend) unsafe fn syscall2( 112 nr: SyscallNumber<'_>, 113 a0: ArgReg<'_, A0>, 114 a1: ArgReg<'_, A1>, 115 ) -> RetReg<R0> { 116 let x0; 117 let err: usize; 118 asm!( 119 "syscall", 120 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 121 in("$4" /*$a0*/) a0.to_asm(), 122 in("$5" /*$a1*/) a1.to_asm(), 123 lateout("$7" /*$a3*/) err, 124 lateout("$8" /*$a4*/) _, 125 lateout("$9" /*$a5*/) _, 126 lateout("$10" /*$a6*/) _, 127 lateout("$11" /*$a7*/) _, 128 lateout("$12" /*$t0*/) _, 129 lateout("$13" /*$t1*/) _, 130 lateout("$14" /*$t2*/) _, 131 lateout("$15" /*$t3*/) _, 132 lateout("$24" /*$t8*/) _, 133 lateout("$25" /*$t9*/) _, 134 options(nostack, preserves_flags) 135 ); 136 FromAsm::from_asm(if err != 0 { 137 (x0 as usize).wrapping_neg() as *mut _ 138 } else { 139 x0 140 }) 141 } 142 143 #[inline] 144 pub(in crate::backend) unsafe fn syscall2_readonly( 145 nr: SyscallNumber<'_>, 146 a0: ArgReg<'_, A0>, 147 a1: ArgReg<'_, A1>, 148 ) -> RetReg<R0> { 149 let x0; 150 let err: usize; 151 asm!( 152 "syscall", 153 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 154 in("$4" /*$a0*/) a0.to_asm(), 155 in("$5" /*$a1*/) a1.to_asm(), 156 lateout("$7" /*$a3*/) err, 157 lateout("$8" /*$a4*/) _, 158 lateout("$9" /*$a5*/) _, 159 lateout("$10" /*$a6*/) _, 160 lateout("$11" /*$a7*/) _, 161 lateout("$12" /*$t0*/) _, 162 lateout("$13" /*$t1*/) _, 163 lateout("$14" /*$t2*/) _, 164 lateout("$15" /*$t3*/) _, 165 lateout("$24" /*$t8*/) _, 166 lateout("$25" /*$t9*/) _, 167 options(nostack, preserves_flags, readonly) 168 ); 169 FromAsm::from_asm(if err != 0 { 170 (x0 as usize).wrapping_neg() as *mut _ 171 } else { 172 x0 173 }) 174 } 175 176 #[inline] 177 pub(in crate::backend) unsafe fn syscall3( 178 nr: SyscallNumber<'_>, 179 a0: ArgReg<'_, A0>, 180 a1: ArgReg<'_, A1>, 181 a2: ArgReg<'_, A2>, 182 ) -> RetReg<R0> { 183 let x0; 184 let err: usize; 185 asm!( 186 "syscall", 187 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 188 in("$4" /*$a0*/) a0.to_asm(), 189 in("$5" /*$a1*/) a1.to_asm(), 190 in("$6" /*$a2*/) a2.to_asm(), 191 lateout("$7" /*$a3*/) err, 192 lateout("$8" /*$a4*/) _, 193 lateout("$9" /*$a5*/) _, 194 lateout("$10" /*$a6*/) _, 195 lateout("$11" /*$a7*/) _, 196 lateout("$12" /*$t0*/) _, 197 lateout("$13" /*$t1*/) _, 198 lateout("$14" /*$t2*/) _, 199 lateout("$15" /*$t3*/) _, 200 lateout("$24" /*$t8*/) _, 201 lateout("$25" /*$t9*/) _, 202 options(nostack, preserves_flags) 203 ); 204 FromAsm::from_asm(if err != 0 { 205 (x0 as usize).wrapping_neg() as *mut _ 206 } else { 207 x0 208 }) 209 } 210 211 #[inline] 212 pub(in crate::backend) unsafe fn syscall3_readonly( 213 nr: SyscallNumber<'_>, 214 a0: ArgReg<'_, A0>, 215 a1: ArgReg<'_, A1>, 216 a2: ArgReg<'_, A2>, 217 ) -> RetReg<R0> { 218 let x0; 219 let err: usize; 220 asm!( 221 "syscall", 222 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 223 in("$4" /*$a0*/) a0.to_asm(), 224 in("$5" /*$a1*/) a1.to_asm(), 225 in("$6" /*$a2*/) a2.to_asm(), 226 lateout("$7" /*$a3*/) err, 227 lateout("$8" /*$a4*/) _, 228 lateout("$9" /*$a5*/) _, 229 lateout("$10" /*$a6*/) _, 230 lateout("$11" /*$a7*/) _, 231 lateout("$12" /*$t0*/) _, 232 lateout("$13" /*$t1*/) _, 233 lateout("$14" /*$t2*/) _, 234 lateout("$15" /*$t3*/) _, 235 lateout("$24" /*$t8*/) _, 236 lateout("$25" /*$t9*/) _, 237 options(nostack, preserves_flags, readonly) 238 ); 239 FromAsm::from_asm(if err != 0 { 240 (x0 as usize).wrapping_neg() as *mut _ 241 } else { 242 x0 243 }) 244 } 245 246 #[inline] 247 pub(in crate::backend) unsafe fn syscall4( 248 nr: SyscallNumber<'_>, 249 a0: ArgReg<'_, A0>, 250 a1: ArgReg<'_, A1>, 251 a2: ArgReg<'_, A2>, 252 a3: ArgReg<'_, A3>, 253 ) -> RetReg<R0> { 254 let x0; 255 let err: usize; 256 asm!( 257 "syscall", 258 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 259 in("$4" /*$a0*/) a0.to_asm(), 260 in("$5" /*$a1*/) a1.to_asm(), 261 in("$6" /*$a2*/) a2.to_asm(), 262 inlateout("$7" /*$a3*/) a3.to_asm() => err, 263 lateout("$8" /*$a4*/) _, 264 lateout("$9" /*$a5*/) _, 265 lateout("$10" /*$a6*/) _, 266 lateout("$11" /*$a7*/) _, 267 lateout("$12" /*$t0*/) _, 268 lateout("$13" /*$t1*/) _, 269 lateout("$14" /*$t2*/) _, 270 lateout("$15" /*$t3*/) _, 271 lateout("$24" /*$t8*/) _, 272 lateout("$25" /*$t9*/) _, 273 options(nostack, preserves_flags) 274 ); 275 FromAsm::from_asm(if err != 0 { 276 (x0 as usize).wrapping_neg() as *mut _ 277 } else { 278 x0 279 }) 280 } 281 282 #[inline] 283 pub(in crate::backend) unsafe fn syscall4_readonly( 284 nr: SyscallNumber<'_>, 285 a0: ArgReg<'_, A0>, 286 a1: ArgReg<'_, A1>, 287 a2: ArgReg<'_, A2>, 288 a3: ArgReg<'_, A3>, 289 ) -> RetReg<R0> { 290 let x0; 291 let err: usize; 292 asm!( 293 "syscall", 294 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 295 in("$4" /*$a0*/) a0.to_asm(), 296 in("$5" /*$a1*/) a1.to_asm(), 297 in("$6" /*$a2*/) a2.to_asm(), 298 inlateout("$7" /*$a3*/) a3.to_asm() => err, 299 lateout("$8" /*$a4*/) _, 300 lateout("$9" /*$a5*/) _, 301 lateout("$10" /*$a6*/) _, 302 lateout("$11" /*$a7*/) _, 303 lateout("$12" /*$t0*/) _, 304 lateout("$13" /*$t1*/) _, 305 lateout("$14" /*$t2*/) _, 306 lateout("$15" /*$t3*/) _, 307 lateout("$24" /*$t8*/) _, 308 lateout("$25" /*$t9*/) _, 309 options(nostack, preserves_flags, readonly) 310 ); 311 FromAsm::from_asm(if err != 0 { 312 (x0 as usize).wrapping_neg() as *mut _ 313 } else { 314 x0 315 }) 316 } 317 318 #[inline] 319 pub(in crate::backend) unsafe fn syscall5( 320 nr: SyscallNumber<'_>, 321 a0: ArgReg<'_, A0>, 322 a1: ArgReg<'_, A1>, 323 a2: ArgReg<'_, A2>, 324 a3: ArgReg<'_, A3>, 325 a4: ArgReg<'_, A4>, 326 ) -> RetReg<R0> { 327 let x0; 328 let err: usize; 329 asm!( 330 "syscall", 331 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 332 in("$4" /*$a0*/) a0.to_asm(), 333 in("$5" /*$a1*/) a1.to_asm(), 334 in("$6" /*$a2*/) a2.to_asm(), 335 inlateout("$7" /*$a3*/) a3.to_asm() => err, 336 inlateout("$8" /*$a4*/) a4.to_asm() => _, 337 lateout("$9" /*$a5*/) _, 338 lateout("$10" /*$a6*/) _, 339 lateout("$11" /*$a7*/) _, 340 lateout("$12" /*$t0*/) _, 341 lateout("$13" /*$t1*/) _, 342 lateout("$14" /*$t2*/) _, 343 lateout("$15" /*$t3*/) _, 344 lateout("$24" /*$t8*/) _, 345 lateout("$25" /*$t9*/) _, 346 options(nostack, preserves_flags) 347 ); 348 FromAsm::from_asm(if err != 0 { 349 (x0 as usize).wrapping_neg() as *mut _ 350 } else { 351 x0 352 }) 353 } 354 355 #[inline] 356 pub(in crate::backend) unsafe fn syscall5_readonly( 357 nr: SyscallNumber<'_>, 358 a0: ArgReg<'_, A0>, 359 a1: ArgReg<'_, A1>, 360 a2: ArgReg<'_, A2>, 361 a3: ArgReg<'_, A3>, 362 a4: ArgReg<'_, A4>, 363 ) -> RetReg<R0> { 364 let x0; 365 let err: usize; 366 asm!( 367 "syscall", 368 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 369 in("$4" /*$a0*/) a0.to_asm(), 370 in("$5" /*$a1*/) a1.to_asm(), 371 in("$6" /*$a2*/) a2.to_asm(), 372 inlateout("$7" /*$a3*/) a3.to_asm() => err, 373 inlateout("$8" /*$a4*/) a4.to_asm() => _, 374 lateout("$9" /*$a5*/) _, 375 lateout("$10" /*$a6*/) _, 376 lateout("$11" /*$a7*/) _, 377 lateout("$12" /*$t0*/) _, 378 lateout("$13" /*$t1*/) _, 379 lateout("$14" /*$t2*/) _, 380 lateout("$15" /*$t3*/) _, 381 lateout("$24" /*$t8*/) _, 382 lateout("$25" /*$t9*/) _, 383 options(nostack, preserves_flags, readonly) 384 ); 385 FromAsm::from_asm(if err != 0 { 386 (x0 as usize).wrapping_neg() as *mut _ 387 } else { 388 x0 389 }) 390 } 391 392 #[inline] 393 pub(in crate::backend) unsafe fn syscall6( 394 nr: SyscallNumber<'_>, 395 a0: ArgReg<'_, A0>, 396 a1: ArgReg<'_, A1>, 397 a2: ArgReg<'_, A2>, 398 a3: ArgReg<'_, A3>, 399 a4: ArgReg<'_, A4>, 400 a5: ArgReg<'_, A5>, 401 ) -> RetReg<R0> { 402 let x0; 403 let err: usize; 404 asm!( 405 "syscall", 406 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 407 in("$4" /*$a0*/) a0.to_asm(), 408 in("$5" /*$a1*/) a1.to_asm(), 409 in("$6" /*$a2*/) a2.to_asm(), 410 inlateout("$7" /*$a3*/) a3.to_asm() => err, 411 inlateout("$8" /*$a4*/) a4.to_asm() => _, 412 inlateout("$9" /*$a5*/) a5.to_asm() => _, 413 lateout("$10" /*$a6*/) _, 414 lateout("$11" /*$a7*/) _, 415 lateout("$12" /*$t0*/) _, 416 lateout("$13" /*$t1*/) _, 417 lateout("$14" /*$t2*/) _, 418 lateout("$15" /*$t3*/) _, 419 lateout("$24" /*$t8*/) _, 420 lateout("$25" /*$t9*/) _, 421 options(nostack, preserves_flags) 422 ); 423 FromAsm::from_asm(if err != 0 { 424 (x0 as usize).wrapping_neg() as *mut _ 425 } else { 426 x0 427 }) 428 } 429 430 #[inline] 431 pub(in crate::backend) unsafe fn syscall6_readonly( 432 nr: SyscallNumber<'_>, 433 a0: ArgReg<'_, A0>, 434 a1: ArgReg<'_, A1>, 435 a2: ArgReg<'_, A2>, 436 a3: ArgReg<'_, A3>, 437 a4: ArgReg<'_, A4>, 438 a5: ArgReg<'_, A5>, 439 ) -> RetReg<R0> { 440 let x0; 441 let err: usize; 442 asm!( 443 "syscall", 444 inlateout("$2" /*$v0*/) nr.to_asm() => x0, 445 in("$4" /*$a0*/) a0.to_asm(), 446 in("$5" /*$a1*/) a1.to_asm(), 447 in("$6" /*$a2*/) a2.to_asm(), 448 inlateout("$7" /*$a3*/) a3.to_asm() => err, 449 inlateout("$8" /*$a4*/) a4.to_asm() => _, 450 inlateout("$9" /*$a5*/) a5.to_asm() => _, 451 lateout("$10" /*$a6*/) _, 452 lateout("$11" /*$a7*/) _, 453 lateout("$12" /*$t0*/) _, 454 lateout("$13" /*$t1*/) _, 455 lateout("$14" /*$t2*/) _, 456 lateout("$15" /*$t3*/) _, 457 lateout("$24" /*$t8*/) _, 458 lateout("$25" /*$t9*/) _, 459 options(nostack, preserves_flags, readonly) 460 ); 461 FromAsm::from_asm(if err != 0 { 462 (x0 as usize).wrapping_neg() as *mut _ 463 } else { 464 x0 465 }) 466 } 467