github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/runtime/sys_linux_ppc64x.s (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 //go:build linux && (ppc64 || ppc64le) 6 7 // 8 // System calls and other sys.stuff for ppc64, Linux 9 // 10 11 #include "go_asm.h" 12 #include "go_tls.h" 13 #include "textflag.h" 14 #include "asm_ppc64x.h" 15 16 #define SYS_exit 1 17 #define SYS_read 3 18 #define SYS_write 4 19 #define SYS_open 5 20 #define SYS_close 6 21 #define SYS_getpid 20 22 #define SYS_kill 37 23 #define SYS_brk 45 24 #define SYS_mmap 90 25 #define SYS_munmap 91 26 #define SYS_setitimer 104 27 #define SYS_clone 120 28 #define SYS_sched_yield 158 29 #define SYS_nanosleep 162 30 #define SYS_rt_sigreturn 172 31 #define SYS_rt_sigaction 173 32 #define SYS_rt_sigprocmask 174 33 #define SYS_sigaltstack 185 34 #define SYS_madvise 205 35 #define SYS_mincore 206 36 #define SYS_gettid 207 37 #define SYS_futex 221 38 #define SYS_sched_getaffinity 223 39 #define SYS_exit_group 234 40 #define SYS_timer_create 240 41 #define SYS_timer_settime 241 42 #define SYS_timer_delete 244 43 #define SYS_clock_gettime 246 44 #define SYS_tgkill 250 45 #define SYS_pipe2 317 46 47 TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4 48 MOVW code+0(FP), R3 49 SYSCALL $SYS_exit_group 50 RET 51 52 // func exitThread(wait *atomic.Uint32) 53 TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8 54 MOVD wait+0(FP), R1 55 // We're done using the stack. 56 MOVW $0, R2 57 SYNC 58 MOVW R2, (R1) 59 MOVW $0, R3 // exit code 60 SYSCALL $SYS_exit 61 JMP 0(PC) 62 63 TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20 64 MOVD name+0(FP), R3 65 MOVW mode+8(FP), R4 66 MOVW perm+12(FP), R5 67 SYSCALL $SYS_open 68 BVC 2(PC) 69 MOVW $-1, R3 70 MOVW R3, ret+16(FP) 71 RET 72 73 TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12 74 MOVW fd+0(FP), R3 75 SYSCALL $SYS_close 76 BVC 2(PC) 77 MOVW $-1, R3 78 MOVW R3, ret+8(FP) 79 RET 80 81 TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28 82 MOVD fd+0(FP), R3 83 MOVD p+8(FP), R4 84 MOVW n+16(FP), R5 85 SYSCALL $SYS_write 86 BVC 2(PC) 87 NEG R3 // caller expects negative errno 88 MOVW R3, ret+24(FP) 89 RET 90 91 TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28 92 MOVW fd+0(FP), R3 93 MOVD p+8(FP), R4 94 MOVW n+16(FP), R5 95 SYSCALL $SYS_read 96 BVC 2(PC) 97 NEG R3 // caller expects negative errno 98 MOVW R3, ret+24(FP) 99 RET 100 101 // func pipe2(flags int32) (r, w int32, errno int32) 102 TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20 103 ADD $FIXED_FRAME+8, R1, R3 104 MOVW flags+0(FP), R4 105 SYSCALL $SYS_pipe2 106 MOVW R3, errno+16(FP) 107 RET 108 109 TEXT runtime·usleep(SB),NOSPLIT,$16-4 110 MOVW usec+0(FP), R3 111 MOVD R3, R5 112 MOVW $1000000, R4 113 DIVD R4, R3 114 MOVD R3, 8(R1) 115 MOVW $1000, R4 116 MULLD R3, R4 117 SUB R4, R5 118 MOVD R5, 16(R1) 119 120 // nanosleep(&ts, 0) 121 ADD $8, R1, R3 122 MOVW $0, R4 123 SYSCALL $SYS_nanosleep 124 RET 125 126 TEXT runtime·gettid(SB),NOSPLIT,$0-4 127 SYSCALL $SYS_gettid 128 MOVW R3, ret+0(FP) 129 RET 130 131 TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0 132 SYSCALL $SYS_getpid 133 MOVW R3, R14 134 SYSCALL $SYS_gettid 135 MOVW R3, R4 // arg 2 tid 136 MOVW R14, R3 // arg 1 pid 137 MOVW sig+0(FP), R5 // arg 3 138 SYSCALL $SYS_tgkill 139 RET 140 141 TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0 142 SYSCALL $SYS_getpid 143 MOVW R3, R3 // arg 1 pid 144 MOVW sig+0(FP), R4 // arg 2 145 SYSCALL $SYS_kill 146 RET 147 148 TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8 149 SYSCALL $SYS_getpid 150 MOVD R3, ret+0(FP) 151 RET 152 153 TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24 154 MOVD tgid+0(FP), R3 155 MOVD tid+8(FP), R4 156 MOVD sig+16(FP), R5 157 SYSCALL $SYS_tgkill 158 RET 159 160 TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24 161 MOVW mode+0(FP), R3 162 MOVD new+8(FP), R4 163 MOVD old+16(FP), R5 164 SYSCALL $SYS_setitimer 165 RET 166 167 TEXT runtime·timer_create(SB),NOSPLIT,$0-28 168 MOVW clockid+0(FP), R3 169 MOVD sevp+8(FP), R4 170 MOVD timerid+16(FP), R5 171 SYSCALL $SYS_timer_create 172 MOVW R3, ret+24(FP) 173 RET 174 175 TEXT runtime·timer_settime(SB),NOSPLIT,$0-28 176 MOVW timerid+0(FP), R3 177 MOVW flags+4(FP), R4 178 MOVD new+8(FP), R5 179 MOVD old+16(FP), R6 180 SYSCALL $SYS_timer_settime 181 MOVW R3, ret+24(FP) 182 RET 183 184 TEXT runtime·timer_delete(SB),NOSPLIT,$0-12 185 MOVW timerid+0(FP), R3 186 SYSCALL $SYS_timer_delete 187 MOVW R3, ret+8(FP) 188 RET 189 190 TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28 191 MOVD addr+0(FP), R3 192 MOVD n+8(FP), R4 193 MOVD dst+16(FP), R5 194 SYSCALL $SYS_mincore 195 NEG R3 // caller expects negative errno 196 MOVW R3, ret+24(FP) 197 RET 198 199 // func walltime() (sec int64, nsec int32) 200 TEXT runtime·walltime(SB),NOSPLIT,$16-12 201 MOVD R1, R15 // R15 is unchanged by C code 202 MOVD g_m(g), R21 // R21 = m 203 204 MOVD $0, R3 // CLOCK_REALTIME 205 206 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability 207 CMP R12, R0 208 BEQ fallback 209 210 // Set vdsoPC and vdsoSP for SIGPROF traceback. 211 // Save the old values on stack and restore them on exit, 212 // so this function is reentrant. 213 MOVD m_vdsoPC(R21), R4 214 MOVD m_vdsoSP(R21), R5 215 MOVD R4, 32(R1) 216 MOVD R5, 40(R1) 217 218 MOVD LR, R14 219 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP 220 MOVD R14, m_vdsoPC(R21) 221 MOVD R5, m_vdsoSP(R21) 222 223 MOVD m_curg(R21), R6 224 CMP g, R6 225 BNE noswitch 226 227 MOVD m_g0(R21), R7 228 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack 229 230 noswitch: 231 SUB $16, R1 // Space for results 232 RLDICR $0, R1, $59, R1 // Align for C code 233 MOVD R12, CTR 234 MOVD R1, R4 235 236 // Store g on gsignal's stack, so if we receive a signal 237 // during VDSO code we can find the g. 238 // If we don't have a signal stack, we won't receive signal, 239 // so don't bother saving g. 240 // When using cgo, we already saved g on TLS, also don't save 241 // g here. 242 // Also don't save g if we are already on the signal stack. 243 // We won't get a nested signal. 244 MOVBZ runtime·iscgo(SB), R22 245 CMP R22, $0 246 BNE nosaveg 247 MOVD m_gsignal(R21), R22 // g.m.gsignal 248 CMP R22, $0 249 BEQ nosaveg 250 251 CMP g, R22 252 BEQ nosaveg 253 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo 254 MOVD g, (R22) 255 256 BL (CTR) // Call from VDSO 257 258 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code 259 260 JMP finish 261 262 nosaveg: 263 BL (CTR) // Call from VDSO 264 265 finish: 266 MOVD $0, R0 // Restore R0 267 MOVD 0(R1), R3 // sec 268 MOVD 8(R1), R5 // nsec 269 MOVD R15, R1 // Restore SP 270 271 // Restore vdsoPC, vdsoSP 272 // We don't worry about being signaled between the two stores. 273 // If we are not in a signal handler, we'll restore vdsoSP to 0, 274 // and no one will care about vdsoPC. If we are in a signal handler, 275 // we cannot receive another signal. 276 MOVD 40(R1), R6 277 MOVD R6, m_vdsoSP(R21) 278 MOVD 32(R1), R6 279 MOVD R6, m_vdsoPC(R21) 280 281 return: 282 MOVD R3, sec+0(FP) 283 MOVW R5, nsec+8(FP) 284 RET 285 286 // Syscall fallback 287 fallback: 288 ADD $32, R1, R4 289 SYSCALL $SYS_clock_gettime 290 MOVD 32(R1), R3 291 MOVD 40(R1), R5 292 JMP return 293 294 TEXT runtime·nanotime1(SB),NOSPLIT,$16-8 295 MOVD $1, R3 // CLOCK_MONOTONIC 296 297 MOVD R1, R15 // R15 is unchanged by C code 298 MOVD g_m(g), R21 // R21 = m 299 300 MOVD runtime·vdsoClockgettimeSym(SB), R12 // Check for VDSO availability 301 CMP R12, R0 302 BEQ fallback 303 304 // Set vdsoPC and vdsoSP for SIGPROF traceback. 305 // Save the old values on stack and restore them on exit, 306 // so this function is reentrant. 307 MOVD m_vdsoPC(R21), R4 308 MOVD m_vdsoSP(R21), R5 309 MOVD R4, 32(R1) 310 MOVD R5, 40(R1) 311 312 MOVD LR, R14 // R14 is unchanged by C code 313 MOVD $ret-FIXED_FRAME(FP), R5 // caller's SP 314 MOVD R14, m_vdsoPC(R21) 315 MOVD R5, m_vdsoSP(R21) 316 317 MOVD m_curg(R21), R6 318 CMP g, R6 319 BNE noswitch 320 321 MOVD m_g0(R21), R7 322 MOVD (g_sched+gobuf_sp)(R7), R1 // Set SP to g0 stack 323 324 noswitch: 325 SUB $16, R1 // Space for results 326 RLDICR $0, R1, $59, R1 // Align for C code 327 MOVD R12, CTR 328 MOVD R1, R4 329 330 // Store g on gsignal's stack, so if we receive a signal 331 // during VDSO code we can find the g. 332 // If we don't have a signal stack, we won't receive signal, 333 // so don't bother saving g. 334 // When using cgo, we already saved g on TLS, also don't save 335 // g here. 336 // Also don't save g if we are already on the signal stack. 337 // We won't get a nested signal. 338 MOVBZ runtime·iscgo(SB), R22 339 CMP R22, $0 340 BNE nosaveg 341 MOVD m_gsignal(R21), R22 // g.m.gsignal 342 CMP R22, $0 343 BEQ nosaveg 344 345 CMP g, R22 346 BEQ nosaveg 347 MOVD (g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo 348 MOVD g, (R22) 349 350 BL (CTR) // Call from VDSO 351 352 MOVD $0, (R22) // clear g slot, R22 is unchanged by C code 353 354 JMP finish 355 356 nosaveg: 357 BL (CTR) // Call from VDSO 358 359 finish: 360 MOVD $0, R0 // Restore R0 361 MOVD 0(R1), R3 // sec 362 MOVD 8(R1), R5 // nsec 363 MOVD R15, R1 // Restore SP 364 365 // Restore vdsoPC, vdsoSP 366 // We don't worry about being signaled between the two stores. 367 // If we are not in a signal handler, we'll restore vdsoSP to 0, 368 // and no one will care about vdsoPC. If we are in a signal handler, 369 // we cannot receive another signal. 370 MOVD 40(R1), R6 371 MOVD R6, m_vdsoSP(R21) 372 MOVD 32(R1), R6 373 MOVD R6, m_vdsoPC(R21) 374 375 return: 376 // sec is in R3, nsec in R5 377 // return nsec in R3 378 MOVD $1000000000, R4 379 MULLD R4, R3 380 ADD R5, R3 381 MOVD R3, ret+0(FP) 382 RET 383 384 // Syscall fallback 385 fallback: 386 ADD $32, R1, R4 387 SYSCALL $SYS_clock_gettime 388 MOVD 32(R1), R3 389 MOVD 40(R1), R5 390 JMP return 391 392 TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28 393 MOVW how+0(FP), R3 394 MOVD new+8(FP), R4 395 MOVD old+16(FP), R5 396 MOVW size+24(FP), R6 397 SYSCALL $SYS_rt_sigprocmask 398 BVC 2(PC) 399 MOVD R0, 0xf0(R0) // crash 400 RET 401 402 TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36 403 MOVD sig+0(FP), R3 404 MOVD new+8(FP), R4 405 MOVD old+16(FP), R5 406 MOVD size+24(FP), R6 407 SYSCALL $SYS_rt_sigaction 408 BVC 2(PC) 409 NEG R3 // caller expects negative errno 410 MOVW R3, ret+32(FP) 411 RET 412 413 #ifdef GOARCH_ppc64le 414 // Call the function stored in _cgo_sigaction using the GCC calling convention. 415 TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0 416 MOVD sig+0(FP), R3 417 MOVD new+8(FP), R4 418 MOVD old+16(FP), R5 419 MOVD _cgo_sigaction(SB), R12 420 MOVD R12, CTR // R12 should contain the function address 421 MOVD R1, R15 // Save R1 422 MOVD R2, 24(R1) // Save R2 423 SUB $48, R1 // reserve 32 (frame) + 16 bytes for sp-8 where fp may be saved. 424 RLDICR $0, R1, $59, R1 // Align to 16 bytes for C code 425 BL (CTR) 426 XOR R0, R0, R0 // Clear R0 as Go expects 427 MOVD R15, R1 // Restore R1 428 MOVD 24(R1), R2 // Restore R2 429 MOVW R3, ret+24(FP) // Return result 430 RET 431 #endif 432 433 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32 434 MOVW sig+8(FP), R3 435 MOVD info+16(FP), R4 436 MOVD ctx+24(FP), R5 437 MOVD fn+0(FP), R12 438 MOVD R12, CTR 439 BL (CTR) 440 MOVD 24(R1), R2 441 RET 442 443 TEXT runtime·sigreturn(SB),NOSPLIT,$0-0 444 RET 445 446 #ifdef GOARCH_ppc64le 447 // ppc64le doesn't need function descriptors 448 // Save callee-save registers in the case of signal forwarding. 449 // Same as on ARM64 https://golang.org/issue/31827 . 450 TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0 451 #else 452 // function descriptor for the real sigtramp 453 TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0 454 DWORD $sigtramp<>(SB) 455 DWORD $0 456 DWORD $0 457 TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0 458 #endif 459 // Start with standard C stack frame layout and linkage. 460 MOVD LR, R0 461 MOVD R0, 16(R1) // Save LR in caller's frame. 462 MOVW CR, R0 // Save CR in caller's frame 463 MOVD R0, 8(R1) 464 // The stack must be acquired here and not 465 // in the automatic way based on stack size 466 // since that sequence clobbers R31 before it 467 // gets saved. 468 // We are being ultra safe here in saving the 469 // Vregs. The case where they might need to 470 // be saved is very unlikely. 471 MOVDU R1, -544(R1) 472 MOVD R14, 64(R1) 473 MOVD R15, 72(R1) 474 MOVD R16, 80(R1) 475 MOVD R17, 88(R1) 476 MOVD R18, 96(R1) 477 MOVD R19, 104(R1) 478 MOVD R20, 112(R1) 479 MOVD R21, 120(R1) 480 MOVD R22, 128(R1) 481 MOVD R23, 136(R1) 482 MOVD R24, 144(R1) 483 MOVD R25, 152(R1) 484 MOVD R26, 160(R1) 485 MOVD R27, 168(R1) 486 MOVD R28, 176(R1) 487 MOVD R29, 184(R1) 488 MOVD g, 192(R1) // R30 489 MOVD R31, 200(R1) 490 FMOVD F14, 208(R1) 491 FMOVD F15, 216(R1) 492 FMOVD F16, 224(R1) 493 FMOVD F17, 232(R1) 494 FMOVD F18, 240(R1) 495 FMOVD F19, 248(R1) 496 FMOVD F20, 256(R1) 497 FMOVD F21, 264(R1) 498 FMOVD F22, 272(R1) 499 FMOVD F23, 280(R1) 500 FMOVD F24, 288(R1) 501 FMOVD F25, 296(R1) 502 FMOVD F26, 304(R1) 503 FMOVD F27, 312(R1) 504 FMOVD F28, 320(R1) 505 FMOVD F29, 328(R1) 506 FMOVD F30, 336(R1) 507 FMOVD F31, 344(R1) 508 // Save V regs 509 // STXVD2X and LXVD2X used since 510 // we aren't sure of alignment. 511 // Endianness doesn't matter 512 // if we are just loading and 513 // storing values. 514 MOVD $352, R7 // V20 515 STXVD2X VS52, (R7)(R1) 516 ADD $16, R7 // V21 368 517 STXVD2X VS53, (R7)(R1) 518 ADD $16, R7 // V22 384 519 STXVD2X VS54, (R7)(R1) 520 ADD $16, R7 // V23 400 521 STXVD2X VS55, (R7)(R1) 522 ADD $16, R7 // V24 416 523 STXVD2X VS56, (R7)(R1) 524 ADD $16, R7 // V25 432 525 STXVD2X VS57, (R7)(R1) 526 ADD $16, R7 // V26 448 527 STXVD2X VS58, (R7)(R1) 528 ADD $16, R7 // V27 464 529 STXVD2X VS59, (R7)(R1) 530 ADD $16, R7 // V28 480 531 STXVD2X VS60, (R7)(R1) 532 ADD $16, R7 // V29 496 533 STXVD2X VS61, (R7)(R1) 534 ADD $16, R7 // V30 512 535 STXVD2X VS62, (R7)(R1) 536 ADD $16, R7 // V31 528 537 STXVD2X VS63, (R7)(R1) 538 539 // initialize essential registers (just in case) 540 BL runtime·reginit(SB) 541 542 // this might be called in external code context, 543 // where g is not set. 544 MOVBZ runtime·iscgo(SB), R6 545 CMP R6, $0 546 BEQ 2(PC) 547 BL runtime·load_g(SB) 548 549 MOVW R3, FIXED_FRAME+0(R1) 550 MOVD R4, FIXED_FRAME+8(R1) 551 MOVD R5, FIXED_FRAME+16(R1) 552 MOVD $runtime·sigtrampgo(SB), R12 553 MOVD R12, CTR 554 BL (CTR) 555 MOVD 24(R1), R2 // Should this be here? Where is it saved? 556 // Starts at 64; FIXED_FRAME is 32 557 MOVD 64(R1), R14 558 MOVD 72(R1), R15 559 MOVD 80(R1), R16 560 MOVD 88(R1), R17 561 MOVD 96(R1), R18 562 MOVD 104(R1), R19 563 MOVD 112(R1), R20 564 MOVD 120(R1), R21 565 MOVD 128(R1), R22 566 MOVD 136(R1), R23 567 MOVD 144(R1), R24 568 MOVD 152(R1), R25 569 MOVD 160(R1), R26 570 MOVD 168(R1), R27 571 MOVD 176(R1), R28 572 MOVD 184(R1), R29 573 MOVD 192(R1), g // R30 574 MOVD 200(R1), R31 575 FMOVD 208(R1), F14 576 FMOVD 216(R1), F15 577 FMOVD 224(R1), F16 578 FMOVD 232(R1), F17 579 FMOVD 240(R1), F18 580 FMOVD 248(R1), F19 581 FMOVD 256(R1), F20 582 FMOVD 264(R1), F21 583 FMOVD 272(R1), F22 584 FMOVD 280(R1), F23 585 FMOVD 288(R1), F24 586 FMOVD 292(R1), F25 587 FMOVD 300(R1), F26 588 FMOVD 308(R1), F27 589 FMOVD 316(R1), F28 590 FMOVD 328(R1), F29 591 FMOVD 336(R1), F30 592 FMOVD 344(R1), F31 593 MOVD $352, R7 594 LXVD2X (R7)(R1), VS52 595 ADD $16, R7 // 368 V21 596 LXVD2X (R7)(R1), VS53 597 ADD $16, R7 // 384 V22 598 LXVD2X (R7)(R1), VS54 599 ADD $16, R7 // 400 V23 600 LXVD2X (R7)(R1), VS55 601 ADD $16, R7 // 416 V24 602 LXVD2X (R7)(R1), VS56 603 ADD $16, R7 // 432 V25 604 LXVD2X (R7)(R1), VS57 605 ADD $16, R7 // 448 V26 606 LXVD2X (R7)(R1), VS58 607 ADD $16, R8 // 464 V27 608 LXVD2X (R7)(R1), VS59 609 ADD $16, R7 // 480 V28 610 LXVD2X (R7)(R1), VS60 611 ADD $16, R7 // 496 V29 612 LXVD2X (R7)(R1), VS61 613 ADD $16, R7 // 512 V30 614 LXVD2X (R7)(R1), VS62 615 ADD $16, R7 // 528 V31 616 LXVD2X (R7)(R1), VS63 617 ADD $544, R1 618 MOVD 8(R1), R0 619 MOVFL R0, $0xff 620 MOVD 16(R1), R0 621 MOVD R0, LR 622 623 RET 624 625 #ifdef GOARCH_ppc64le 626 // ppc64le doesn't need function descriptors 627 TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 628 // The stack unwinder, presumably written in C, may not be able to 629 // handle Go frame correctly. So, this function is NOFRAME, and we 630 // save/restore LR manually. 631 MOVD LR, R10 632 633 // We're coming from C code, initialize essential registers. 634 CALL runtime·reginit(SB) 635 636 // If no traceback function, do usual sigtramp. 637 MOVD runtime·cgoTraceback(SB), R6 638 CMP $0, R6 639 BEQ sigtramp 640 641 // If no traceback support function, which means that 642 // runtime/cgo was not linked in, do usual sigtramp. 643 MOVD _cgo_callers(SB), R6 644 CMP $0, R6 645 BEQ sigtramp 646 647 // Set up g register. 648 CALL runtime·load_g(SB) 649 650 // Figure out if we are currently in a cgo call. 651 // If not, just do usual sigtramp. 652 // compared to ARM64 and others. 653 CMP $0, g 654 BEQ sigtrampnog // g == nil 655 MOVD g_m(g), R6 656 CMP $0, R6 657 BEQ sigtramp // g.m == nil 658 MOVW m_ncgo(R6), R7 659 CMPW $0, R7 660 BEQ sigtramp // g.m.ncgo = 0 661 MOVD m_curg(R6), R7 662 CMP $0, R7 663 BEQ sigtramp // g.m.curg == nil 664 MOVD g_syscallsp(R7), R7 665 CMP $0, R7 666 BEQ sigtramp // g.m.curg.syscallsp == 0 667 MOVD m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention. 668 CMP $0, R7 669 BEQ sigtramp // g.m.cgoCallers == nil 670 MOVW m_cgoCallersUse(R6), R8 671 CMPW $0, R8 672 BNE sigtramp // g.m.cgoCallersUse != 0 673 674 // Jump to a function in runtime/cgo. 675 // That function, written in C, will call the user's traceback 676 // function with proper unwind info, and will then call back here. 677 // The first three arguments, and the fifth, are already in registers. 678 // Set the two remaining arguments now. 679 MOVD runtime·cgoTraceback(SB), R6 680 MOVD $runtime·sigtramp(SB), R8 681 MOVD _cgo_callers(SB), R12 682 MOVD R12, CTR 683 MOVD R10, LR // restore LR 684 JMP (CTR) 685 686 sigtramp: 687 MOVD R10, LR // restore LR 688 JMP runtime·sigtramp(SB) 689 690 sigtrampnog: 691 // Signal arrived on a non-Go thread. If this is SIGPROF, get a 692 // stack trace. 693 CMPW R3, $27 // 27 == SIGPROF 694 BNE sigtramp 695 696 // Lock sigprofCallersUse (cas from 0 to 1). 697 MOVW $1, R7 698 MOVD $runtime·sigprofCallersUse(SB), R8 699 SYNC 700 LWAR (R8), R6 701 CMPW $0, R6 702 BNE sigtramp 703 STWCCC R7, (R8) 704 BNE -4(PC) 705 ISYNC 706 707 // Jump to the traceback function in runtime/cgo. 708 // It will call back to sigprofNonGo, which will ignore the 709 // arguments passed in registers. 710 // First three arguments to traceback function are in registers already. 711 MOVD runtime·cgoTraceback(SB), R6 712 MOVD $runtime·sigprofCallers(SB), R7 713 MOVD $runtime·sigprofNonGoWrapper<>(SB), R8 714 MOVD _cgo_callers(SB), R12 715 MOVD R12, CTR 716 MOVD R10, LR // restore LR 717 JMP (CTR) 718 #else 719 // function descriptor for the real sigtramp 720 TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0 721 DWORD $cgoSigtramp<>(SB) 722 DWORD $0 723 DWORD $0 724 TEXT cgoSigtramp<>(SB),NOSPLIT,$0 725 JMP sigtramp<>(SB) 726 #endif 727 728 TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT,$0 729 // We're coming from C code, set up essential register, then call sigprofNonGo. 730 CALL runtime·reginit(SB) 731 MOVW R3, FIXED_FRAME+0(R1) // sig 732 MOVD R4, FIXED_FRAME+8(R1) // info 733 MOVD R5, FIXED_FRAME+16(R1) // ctx 734 CALL runtime·sigprofNonGo(SB) 735 RET 736 737 TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0 738 MOVD addr+0(FP), R3 739 MOVD n+8(FP), R4 740 MOVW prot+16(FP), R5 741 MOVW flags+20(FP), R6 742 MOVW fd+24(FP), R7 743 MOVW off+28(FP), R8 744 745 SYSCALL $SYS_mmap 746 BVC ok 747 MOVD $0, p+32(FP) 748 MOVD R3, err+40(FP) 749 RET 750 ok: 751 MOVD R3, p+32(FP) 752 MOVD $0, err+40(FP) 753 RET 754 755 TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0 756 MOVD addr+0(FP), R3 757 MOVD n+8(FP), R4 758 SYSCALL $SYS_munmap 759 BVC 2(PC) 760 MOVD R0, 0xf0(R0) 761 RET 762 763 TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0 764 MOVD addr+0(FP), R3 765 MOVD n+8(FP), R4 766 MOVW flags+16(FP), R5 767 SYSCALL $SYS_madvise 768 MOVW R3, ret+24(FP) 769 RET 770 771 // int64 futex(int32 *uaddr, int32 op, int32 val, 772 // struct timespec *timeout, int32 *uaddr2, int32 val2); 773 TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0 774 MOVD addr+0(FP), R3 775 MOVW op+8(FP), R4 776 MOVW val+12(FP), R5 777 MOVD ts+16(FP), R6 778 MOVD addr2+24(FP), R7 779 MOVW val3+32(FP), R8 780 SYSCALL $SYS_futex 781 BVC 2(PC) 782 NEG R3 // caller expects negative errno 783 MOVW R3, ret+40(FP) 784 RET 785 786 // int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void)); 787 TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0 788 MOVW flags+0(FP), R3 789 MOVD stk+8(FP), R4 790 791 // Copy mp, gp, fn off parent stack for use by child. 792 // Careful: Linux system call clobbers ???. 793 MOVD mp+16(FP), R7 794 MOVD gp+24(FP), R8 795 MOVD fn+32(FP), R12 796 797 MOVD R7, -8(R4) 798 MOVD R8, -16(R4) 799 MOVD R12, -24(R4) 800 MOVD $1234, R7 801 MOVD R7, -32(R4) 802 803 SYSCALL $SYS_clone 804 BVC 2(PC) 805 NEG R3 // caller expects negative errno 806 807 // In parent, return. 808 CMP R3, $0 809 BEQ 3(PC) 810 MOVW R3, ret+40(FP) 811 RET 812 813 // In child, on new stack. 814 // initialize essential registers 815 BL runtime·reginit(SB) 816 MOVD -32(R1), R7 817 CMP R7, $1234 818 BEQ 2(PC) 819 MOVD R0, 0(R0) 820 821 // Initialize m->procid to Linux tid 822 SYSCALL $SYS_gettid 823 824 MOVD -24(R1), R12 // fn 825 MOVD -16(R1), R8 // g 826 MOVD -8(R1), R7 // m 827 828 CMP R7, $0 829 BEQ nog 830 CMP R8, $0 831 BEQ nog 832 833 MOVD R3, m_procid(R7) 834 835 // TODO: setup TLS. 836 837 // In child, set up new stack 838 MOVD R7, g_m(R8) 839 MOVD R8, g 840 //CALL runtime·stackcheck(SB) 841 842 nog: 843 // Call fn 844 MOVD R12, CTR 845 BL (CTR) 846 847 // It shouldn't return. If it does, exit that thread. 848 MOVW $111, R3 849 SYSCALL $SYS_exit 850 BR -2(PC) // keep exiting 851 852 TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0 853 MOVD new+0(FP), R3 854 MOVD old+8(FP), R4 855 SYSCALL $SYS_sigaltstack 856 BVC 2(PC) 857 MOVD R0, 0xf0(R0) // crash 858 RET 859 860 TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0 861 SYSCALL $SYS_sched_yield 862 RET 863 864 TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0 865 MOVD pid+0(FP), R3 866 MOVD len+8(FP), R4 867 MOVD buf+16(FP), R5 868 SYSCALL $SYS_sched_getaffinity 869 BVC 2(PC) 870 NEG R3 // caller expects negative errno 871 MOVW R3, ret+24(FP) 872 RET 873 874 // func sbrk0() uintptr 875 TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0 876 // Implemented as brk(NULL). 877 MOVD $0, R3 878 SYSCALL $SYS_brk 879 MOVD R3, ret+0(FP) 880 RET 881 882 TEXT runtime·access(SB),$0-20 883 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go 884 MOVW R0, ret+16(FP) // for vet 885 RET 886 887 TEXT runtime·connect(SB),$0-28 888 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go 889 MOVW R0, ret+24(FP) // for vet 890 RET 891 892 TEXT runtime·socket(SB),$0-20 893 MOVD R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go 894 MOVW R0, ret+16(FP) // for vet 895 RET