1 //! powerpc64le Linux system calls. 2 //! 3 //! On powerpc64le, Linux indicates success or failure using `cr0.SO` rather 4 //! than by returning a negative error code as most other architectures do. In 5 //! theory we could immediately translate this into a `Result`, and it'd save a 6 //! few branches. And in theory we could have specialized sequences for use 7 //! with syscalls that are known to never fail. However, those would require 8 //! more extensive changes in rustix's platform-independent code. For now, we 9 //! check the flag and negate the error value to make PowerPC64 look like other 10 //! architectures. 11 12 use crate::backend::reg::{ 13 ArgReg, FromAsm, RetReg, SyscallNumber, ToAsm, A0, A1, A2, A3, A4, A5, R0, 14 }; 15 use core::arch::asm; 16 17 #[inline] 18 pub(in crate::backend) unsafe fn syscall0_readonly(nr: SyscallNumber) -> RetReg<R0> { 19 let r0; 20 asm!( 21 "sc", 22 "bns 0f", 23 "neg 3, 3", 24 "0:", 25 inlateout("r0") nr.to_asm() => _, 26 lateout("r3") r0, 27 lateout("r4") _, 28 lateout("r5") _, 29 lateout("r6") _, 30 lateout("r7") _, 31 lateout("r8") _, 32 lateout("r9") _, 33 lateout("r10") _, 34 lateout("r11") _, 35 lateout("r12") _, 36 lateout("cr0") _, 37 options(nostack, preserves_flags, readonly) 38 ); 39 FromAsm::from_asm(r0) 40 } 41 42 #[inline] 43 pub(in crate::backend) unsafe fn syscall1(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> RetReg<R0> { 44 let r0; 45 asm!( 46 "sc", 47 "bns 0f", 48 "neg 3, 3", 49 "0:", 50 inlateout("r0") nr.to_asm() => _, 51 inlateout("r3") a0.to_asm() => r0, 52 lateout("r4") _, 53 lateout("r5") _, 54 lateout("r6") _, 55 lateout("r7") _, 56 lateout("r8") _, 57 lateout("r9") _, 58 lateout("r10") _, 59 lateout("r11") _, 60 lateout("r12") _, 61 lateout("cr0") _, 62 options(nostack, preserves_flags) 63 ); 64 FromAsm::from_asm(r0) 65 } 66 67 #[inline] 68 pub(in crate::backend) unsafe fn syscall1_readonly( 69 nr: SyscallNumber<'_>, 70 a0: ArgReg<'_, A0>, 71 ) -> RetReg<R0> { 72 let r0; 73 asm!( 74 "sc", 75 "bns 0f", 76 "neg 3, 3", 77 "0:", 78 inlateout("r0") nr.to_asm() => _, 79 inlateout("r3") a0.to_asm() => r0, 80 lateout("r4") _, 81 lateout("r5") _, 82 lateout("r6") _, 83 lateout("r7") _, 84 lateout("r8") _, 85 lateout("r9") _, 86 lateout("r10") _, 87 lateout("r11") _, 88 lateout("r12") _, 89 lateout("cr0") _, 90 options(nostack, preserves_flags, readonly) 91 ); 92 FromAsm::from_asm(r0) 93 } 94 95 #[inline] 96 pub(in crate::backend) unsafe fn syscall1_noreturn(nr: SyscallNumber<'_>, a0: ArgReg<'_, A0>) -> ! { 97 asm!( 98 "sc", 99 in("r0") nr.to_asm(), 100 in("r3") a0.to_asm(), 101 options(noreturn) 102 ) 103 } 104 105 #[inline] 106 pub(in crate::backend) unsafe fn syscall2( 107 nr: SyscallNumber<'_>, 108 a0: ArgReg<'_, A0>, 109 a1: ArgReg<'_, A1>, 110 ) -> RetReg<R0> { 111 let r0; 112 asm!( 113 "sc", 114 "bns 0f", 115 "neg 3, 3", 116 "0:", 117 inlateout("r0") nr.to_asm() => _, 118 inlateout("r3") a0.to_asm() => r0, 119 inlateout("r4") a1.to_asm() => _, 120 lateout("r5") _, 121 lateout("r6") _, 122 lateout("r7") _, 123 lateout("r8") _, 124 lateout("r9") _, 125 lateout("r10") _, 126 lateout("r11") _, 127 lateout("r12") _, 128 lateout("cr0") _, 129 options(nostack, preserves_flags) 130 ); 131 FromAsm::from_asm(r0) 132 } 133 134 #[inline] 135 pub(in crate::backend) unsafe fn syscall2_readonly( 136 nr: SyscallNumber<'_>, 137 a0: ArgReg<'_, A0>, 138 a1: ArgReg<'_, A1>, 139 ) -> RetReg<R0> { 140 let r0; 141 asm!( 142 "sc", 143 "bns 0f", 144 "neg 3, 3", 145 "0:", 146 inlateout("r0") nr.to_asm() => _, 147 inlateout("r3") a0.to_asm() => r0, 148 inlateout("r4") a1.to_asm() => _, 149 lateout("r5") _, 150 lateout("r6") _, 151 lateout("r7") _, 152 lateout("r8") _, 153 lateout("r9") _, 154 lateout("r10") _, 155 lateout("r11") _, 156 lateout("r12") _, 157 lateout("cr0") _, 158 options(nostack, preserves_flags, readonly) 159 ); 160 FromAsm::from_asm(r0) 161 } 162 163 #[inline] 164 pub(in crate::backend) unsafe fn syscall3( 165 nr: SyscallNumber<'_>, 166 a0: ArgReg<'_, A0>, 167 a1: ArgReg<'_, A1>, 168 a2: ArgReg<'_, A2>, 169 ) -> RetReg<R0> { 170 let r0; 171 asm!( 172 "sc", 173 "bns 0f", 174 "neg 3, 3", 175 "0:", 176 inlateout("r0") nr.to_asm() => _, 177 inlateout("r3") a0.to_asm() => r0, 178 inlateout("r4") a1.to_asm() => _, 179 inlateout("r5") a2.to_asm() => _, 180 lateout("r6") _, 181 lateout("r7") _, 182 lateout("r8") _, 183 lateout("r9") _, 184 lateout("r10") _, 185 lateout("r11") _, 186 lateout("r12") _, 187 lateout("cr0") _, 188 options(nostack, preserves_flags) 189 ); 190 FromAsm::from_asm(r0) 191 } 192 193 #[inline] 194 pub(in crate::backend) unsafe fn syscall3_readonly( 195 nr: SyscallNumber<'_>, 196 a0: ArgReg<'_, A0>, 197 a1: ArgReg<'_, A1>, 198 a2: ArgReg<'_, A2>, 199 ) -> RetReg<R0> { 200 let r0; 201 asm!( 202 "sc", 203 "bns 0f", 204 "neg 3, 3", 205 "0:", 206 inlateout("r0") nr.to_asm() => _, 207 inlateout("r3") a0.to_asm() => r0, 208 inlateout("r4") a1.to_asm() => _, 209 inlateout("r5") a2.to_asm() => _, 210 lateout("r6") _, 211 lateout("r7") _, 212 lateout("r8") _, 213 lateout("r9") _, 214 lateout("r10") _, 215 lateout("r11") _, 216 lateout("r12") _, 217 lateout("cr0") _, 218 options(nostack, preserves_flags, readonly) 219 ); 220 FromAsm::from_asm(r0) 221 } 222 223 #[inline] 224 pub(in crate::backend) unsafe fn syscall4( 225 nr: SyscallNumber<'_>, 226 a0: ArgReg<'_, A0>, 227 a1: ArgReg<'_, A1>, 228 a2: ArgReg<'_, A2>, 229 a3: ArgReg<'_, A3>, 230 ) -> RetReg<R0> { 231 let r0; 232 asm!( 233 "sc", 234 "bns 0f", 235 "neg 3, 3", 236 "0:", 237 inlateout("r0") nr.to_asm() => _, 238 inlateout("r3") a0.to_asm() => r0, 239 inlateout("r4") a1.to_asm() => _, 240 inlateout("r5") a2.to_asm() => _, 241 inlateout("r6") a3.to_asm() => _, 242 lateout("r7") _, 243 lateout("r8") _, 244 lateout("r9") _, 245 lateout("r10") _, 246 lateout("r11") _, 247 lateout("r12") _, 248 lateout("cr0") _, 249 options(nostack, preserves_flags) 250 ); 251 FromAsm::from_asm(r0) 252 } 253 254 #[inline] 255 pub(in crate::backend) unsafe fn syscall4_readonly( 256 nr: SyscallNumber<'_>, 257 a0: ArgReg<'_, A0>, 258 a1: ArgReg<'_, A1>, 259 a2: ArgReg<'_, A2>, 260 a3: ArgReg<'_, A3>, 261 ) -> RetReg<R0> { 262 let r0; 263 asm!( 264 "sc", 265 "bns 0f", 266 "neg 3, 3", 267 "0:", 268 inlateout("r0") nr.to_asm() => _, 269 inlateout("r3") a0.to_asm() => r0, 270 inlateout("r4") a1.to_asm() => _, 271 inlateout("r5") a2.to_asm() => _, 272 inlateout("r6") a3.to_asm() => _, 273 lateout("r7") _, 274 lateout("r8") _, 275 lateout("r9") _, 276 lateout("r10") _, 277 lateout("r11") _, 278 lateout("r12") _, 279 lateout("cr0") _, 280 options(nostack, preserves_flags, readonly) 281 ); 282 FromAsm::from_asm(r0) 283 } 284 285 #[inline] 286 pub(in crate::backend) unsafe fn syscall5( 287 nr: SyscallNumber<'_>, 288 a0: ArgReg<'_, A0>, 289 a1: ArgReg<'_, A1>, 290 a2: ArgReg<'_, A2>, 291 a3: ArgReg<'_, A3>, 292 a4: ArgReg<'_, A4>, 293 ) -> RetReg<R0> { 294 let r0; 295 asm!( 296 "sc", 297 "bns 0f", 298 "neg 3, 3", 299 "0:", 300 inlateout("r0") nr.to_asm() => _, 301 inlateout("r3") a0.to_asm() => r0, 302 inlateout("r4") a1.to_asm() => _, 303 inlateout("r5") a2.to_asm() => _, 304 inlateout("r6") a3.to_asm() => _, 305 inlateout("r7") a4.to_asm() => _, 306 lateout("r8") _, 307 lateout("r9") _, 308 lateout("r10") _, 309 lateout("r11") _, 310 lateout("r12") _, 311 lateout("cr0") _, 312 options(nostack, preserves_flags) 313 ); 314 FromAsm::from_asm(r0) 315 } 316 317 #[inline] 318 pub(in crate::backend) unsafe fn syscall5_readonly( 319 nr: SyscallNumber<'_>, 320 a0: ArgReg<'_, A0>, 321 a1: ArgReg<'_, A1>, 322 a2: ArgReg<'_, A2>, 323 a3: ArgReg<'_, A3>, 324 a4: ArgReg<'_, A4>, 325 ) -> RetReg<R0> { 326 let r0; 327 asm!( 328 "sc", 329 "bns 0f", 330 "neg 3, 3", 331 "0:", 332 inlateout("r0") nr.to_asm() => _, 333 inlateout("r3") a0.to_asm() => r0, 334 inlateout("r4") a1.to_asm() => _, 335 inlateout("r5") a2.to_asm() => _, 336 inlateout("r6") a3.to_asm() => _, 337 inlateout("r7") a4.to_asm() => _, 338 lateout("r8") _, 339 lateout("r9") _, 340 lateout("r10") _, 341 lateout("r11") _, 342 lateout("r12") _, 343 lateout("cr0") _, 344 options(nostack, preserves_flags, readonly) 345 ); 346 FromAsm::from_asm(r0) 347 } 348 349 #[inline] 350 pub(in crate::backend) unsafe fn syscall6( 351 nr: SyscallNumber<'_>, 352 a0: ArgReg<'_, A0>, 353 a1: ArgReg<'_, A1>, 354 a2: ArgReg<'_, A2>, 355 a3: ArgReg<'_, A3>, 356 a4: ArgReg<'_, A4>, 357 a5: ArgReg<'_, A5>, 358 ) -> RetReg<R0> { 359 let r0; 360 asm!( 361 "sc", 362 "bns 0f", 363 "neg 3, 3", 364 "0:", 365 inlateout("r0") nr.to_asm() => _, 366 inlateout("r3") a0.to_asm() => r0, 367 inlateout("r4") a1.to_asm() => _, 368 inlateout("r5") a2.to_asm() => _, 369 inlateout("r6") a3.to_asm() => _, 370 inlateout("r7") a4.to_asm() => _, 371 inlateout("r8") a5.to_asm() => _, 372 lateout("r9") _, 373 lateout("r10") _, 374 lateout("r11") _, 375 lateout("r12") _, 376 lateout("cr0") _, 377 options(nostack, preserves_flags) 378 ); 379 FromAsm::from_asm(r0) 380 } 381 382 #[inline] 383 pub(in crate::backend) unsafe fn syscall6_readonly( 384 nr: SyscallNumber<'_>, 385 a0: ArgReg<'_, A0>, 386 a1: ArgReg<'_, A1>, 387 a2: ArgReg<'_, A2>, 388 a3: ArgReg<'_, A3>, 389 a4: ArgReg<'_, A4>, 390 a5: ArgReg<'_, A5>, 391 ) -> RetReg<R0> { 392 let r0; 393 asm!( 394 "sc", 395 "bns 0f", 396 "neg 3, 3", 397 "0:", 398 inlateout("r0") nr.to_asm() => _, 399 inlateout("r3") a0.to_asm() => r0, 400 inlateout("r4") a1.to_asm() => _, 401 inlateout("r5") a2.to_asm() => _, 402 inlateout("r6") a3.to_asm() => _, 403 inlateout("r7") a4.to_asm() => _, 404 inlateout("r8") a5.to_asm() => _, 405 lateout("r9") _, 406 lateout("r10") _, 407 lateout("r11") _, 408 lateout("r12") _, 409 lateout("cr0") _, 410 options(nostack, preserves_flags, readonly) 411 ); 412 FromAsm::from_asm(r0) 413 } 414