github.com/ice-blockchain/go/src@v0.0.0-20240403114104-1564d284e521/runtime/asm_loong64.s (about) 1 // Copyright 2022 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 #include "go_asm.h" 6 #include "go_tls.h" 7 #include "funcdata.h" 8 #include "textflag.h" 9 10 #define REGCTXT R29 11 12 TEXT runtime·rt0_go(SB),NOSPLIT|TOPFRAME,$0 13 // R3 = stack; R4 = argc; R5 = argv 14 15 ADDV $-24, R3 16 MOVW R4, 8(R3) // argc 17 MOVV R5, 16(R3) // argv 18 19 // create istack out of the given (operating system) stack. 20 // _cgo_init may update stackguard. 21 MOVV $runtime·g0(SB), g 22 MOVV $(-64*1024), R30 23 ADDV R30, R3, R19 24 MOVV R19, g_stackguard0(g) 25 MOVV R19, g_stackguard1(g) 26 MOVV R19, (g_stack+stack_lo)(g) 27 MOVV R3, (g_stack+stack_hi)(g) 28 29 // if there is a _cgo_init, call it using the gcc ABI. 30 MOVV _cgo_init(SB), R25 31 BEQ R25, nocgo 32 33 MOVV R0, R7 // arg 3: not used 34 MOVV R0, R6 // arg 2: not used 35 MOVV $setg_gcc<>(SB), R5 // arg 1: setg 36 MOVV g, R4 // arg 0: G 37 JAL (R25) 38 39 nocgo: 40 // update stackguard after _cgo_init 41 MOVV (g_stack+stack_lo)(g), R19 42 ADDV $const_stackGuard, R19 43 MOVV R19, g_stackguard0(g) 44 MOVV R19, g_stackguard1(g) 45 46 // set the per-goroutine and per-mach "registers" 47 MOVV $runtime·m0(SB), R19 48 49 // save m->g0 = g0 50 MOVV g, m_g0(R19) 51 // save m0 to g0->m 52 MOVV R19, g_m(g) 53 54 JAL runtime·check(SB) 55 56 // args are already prepared 57 JAL runtime·args(SB) 58 JAL runtime·osinit(SB) 59 JAL runtime·schedinit(SB) 60 61 // create a new goroutine to start program 62 MOVV $runtime·mainPC(SB), R19 // entry 63 ADDV $-16, R3 64 MOVV R19, 8(R3) 65 MOVV R0, 0(R3) 66 JAL runtime·newproc(SB) 67 ADDV $16, R3 68 69 // start this M 70 JAL runtime·mstart(SB) 71 72 MOVV R0, 1(R0) 73 RET 74 75 DATA runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB) 76 GLOBL runtime·mainPC(SB),RODATA,$8 77 78 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 79 BREAK 80 RET 81 82 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 83 RET 84 85 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0 86 JAL runtime·mstart0(SB) 87 RET // not reached 88 89 // func cputicks() int64 90 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 91 RDTIMED R0, R4 92 MOVV R4, ret+0(FP) 93 RET 94 95 /* 96 * go-routine 97 */ 98 99 // void gogo(Gobuf*) 100 // restore state from Gobuf; longjmp 101 TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8 102 MOVV buf+0(FP), R4 103 MOVV gobuf_g(R4), R5 104 MOVV 0(R5), R0 // make sure g != nil 105 JMP gogo<>(SB) 106 107 TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 108 MOVV R5, g 109 JAL runtime·save_g(SB) 110 111 MOVV gobuf_sp(R4), R3 112 MOVV gobuf_lr(R4), R1 113 MOVV gobuf_ret(R4), R19 114 MOVV gobuf_ctxt(R4), REGCTXT 115 MOVV R0, gobuf_sp(R4) 116 MOVV R0, gobuf_ret(R4) 117 MOVV R0, gobuf_lr(R4) 118 MOVV R0, gobuf_ctxt(R4) 119 MOVV gobuf_pc(R4), R6 120 JMP (R6) 121 122 // void mcall(fn func(*g)) 123 // Switch to m->g0's stack, call fn(g). 124 // Fn must never return. It should gogo(&g->sched) 125 // to keep running g. 126 TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8 127 #ifdef GOEXPERIMENT_regabiargs 128 MOVV R4, REGCTXT 129 #else 130 MOVV fn+0(FP), REGCTXT 131 #endif 132 133 // Save caller state in g->sched 134 MOVV R3, (g_sched+gobuf_sp)(g) 135 MOVV R1, (g_sched+gobuf_pc)(g) 136 MOVV R0, (g_sched+gobuf_lr)(g) 137 138 // Switch to m->g0 & its stack, call fn. 139 MOVV g, R4 // arg = g 140 MOVV g_m(g), R20 141 MOVV m_g0(R20), g 142 JAL runtime·save_g(SB) 143 BNE g, R4, 2(PC) 144 JMP runtime·badmcall(SB) 145 MOVV 0(REGCTXT), R20 // code pointer 146 MOVV (g_sched+gobuf_sp)(g), R3 // sp = m->g0->sched.sp 147 ADDV $-16, R3 148 MOVV R4, 8(R3) 149 MOVV R0, 0(R3) 150 JAL (R20) 151 JMP runtime·badmcall2(SB) 152 153 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 154 // of the G stack. We need to distinguish the routine that 155 // lives at the bottom of the G stack from the one that lives 156 // at the top of the system stack because the one at the top of 157 // the system stack terminates the stack walk (see topofstack()). 158 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 159 UNDEF 160 JAL (R1) // make sure this function is not leaf 161 RET 162 163 // func systemstack(fn func()) 164 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 165 MOVV fn+0(FP), R19 // R19 = fn 166 MOVV R19, REGCTXT // context 167 MOVV g_m(g), R4 // R4 = m 168 169 MOVV m_gsignal(R4), R5 // R5 = gsignal 170 BEQ g, R5, noswitch 171 172 MOVV m_g0(R4), R5 // R5 = g0 173 BEQ g, R5, noswitch 174 175 MOVV m_curg(R4), R6 176 BEQ g, R6, switch 177 178 // Bad: g is not gsignal, not g0, not curg. What is it? 179 // Hide call from linker nosplit analysis. 180 MOVV $runtime·badsystemstack(SB), R7 181 JAL (R7) 182 JAL runtime·abort(SB) 183 184 switch: 185 // save our state in g->sched. Pretend to 186 // be systemstack_switch if the G stack is scanned. 187 JAL gosave_systemstack_switch<>(SB) 188 189 // switch to g0 190 MOVV R5, g 191 JAL runtime·save_g(SB) 192 MOVV (g_sched+gobuf_sp)(g), R19 193 MOVV R19, R3 194 195 // call target function 196 MOVV 0(REGCTXT), R6 // code pointer 197 JAL (R6) 198 199 // switch back to g 200 MOVV g_m(g), R4 201 MOVV m_curg(R4), g 202 JAL runtime·save_g(SB) 203 MOVV (g_sched+gobuf_sp)(g), R3 204 MOVV R0, (g_sched+gobuf_sp)(g) 205 RET 206 207 noswitch: 208 // already on m stack, just call directly 209 // Using a tail call here cleans up tracebacks since we won't stop 210 // at an intermediate systemstack. 211 MOVV 0(REGCTXT), R4 // code pointer 212 MOVV 0(R3), R1 // restore LR 213 ADDV $8, R3 214 JMP (R4) 215 216 // func switchToCrashStack0(fn func()) 217 TEXT runtime·switchToCrashStack0(SB), NOSPLIT, $0-8 218 MOVV fn+0(FP), REGCTXT // context register 219 MOVV g_m(g), R4 // curm 220 221 // set g to gcrash 222 MOVV $runtime·gcrash(SB), g // g = &gcrash 223 JAL runtime·save_g(SB) 224 MOVV R4, g_m(g) // g.m = curm 225 MOVV g, m_g0(R4) // curm.g0 = g 226 227 // switch to crashstack 228 MOVV (g_stack+stack_hi)(g), R4 229 ADDV $(-4*8), R4, R3 230 231 // call target function 232 MOVV 0(REGCTXT), R6 233 JAL (R6) 234 235 // should never return 236 JAL runtime·abort(SB) 237 UNDEF 238 239 /* 240 * support for morestack 241 */ 242 243 // Called during function prolog when more stack is needed. 244 // Caller has already loaded: 245 // loong64: R31: LR 246 // 247 // The traceback routines see morestack on a g0 as being 248 // the top of a stack (for example, morestack calling newstack 249 // calling the scheduler calling newm calling gc), so we must 250 // record an argument size. For that purpose, it has no arguments. 251 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 252 // Called from f. 253 // Set g->sched to context in f. 254 MOVV R3, (g_sched+gobuf_sp)(g) 255 MOVV R1, (g_sched+gobuf_pc)(g) 256 MOVV R31, (g_sched+gobuf_lr)(g) 257 MOVV REGCTXT, (g_sched+gobuf_ctxt)(g) 258 259 // Cannot grow scheduler stack (m->g0). 260 MOVV g_m(g), R7 261 MOVV m_g0(R7), R8 262 BNE g, R8, 3(PC) 263 JAL runtime·badmorestackg0(SB) 264 JAL runtime·abort(SB) 265 266 // Cannot grow signal stack (m->gsignal). 267 MOVV m_gsignal(R7), R8 268 BNE g, R8, 3(PC) 269 JAL runtime·badmorestackgsignal(SB) 270 JAL runtime·abort(SB) 271 272 // Called from f. 273 // Set m->morebuf to f's caller. 274 MOVV R31, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 275 MOVV R3, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 276 MOVV g, (m_morebuf+gobuf_g)(R7) 277 278 // Call newstack on m->g0's stack. 279 MOVV m_g0(R7), g 280 JAL runtime·save_g(SB) 281 MOVV (g_sched+gobuf_sp)(g), R3 282 // Create a stack frame on g0 to call newstack. 283 MOVV R0, -8(R3) // Zero saved LR in frame 284 ADDV $-8, R3 285 JAL runtime·newstack(SB) 286 287 // Not reached, but make sure the return PC from the call to newstack 288 // is still in this function, and not the beginning of the next. 289 UNDEF 290 291 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 292 // Force SPWRITE. This function doesn't actually write SP, 293 // but it is called with a special calling convention where 294 // the caller doesn't save LR on stack but passes it as a 295 // register (R5), and the unwinder currently doesn't understand. 296 // Make it SPWRITE to stop unwinding. (See issue 54332) 297 MOVV R3, R3 298 299 MOVV R0, REGCTXT 300 JMP runtime·morestack(SB) 301 302 // reflectcall: call a function with the given argument list 303 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). 304 // we don't have variable-sized frames, so we use a small number 305 // of constant-sized-frame functions to encode a few bits of size in the pc. 306 // Caution: ugly multiline assembly macros in your future! 307 308 #define DISPATCH(NAME,MAXSIZE) \ 309 MOVV $MAXSIZE, R30; \ 310 SGTU R19, R30, R30; \ 311 BNE R30, 3(PC); \ 312 MOVV $NAME(SB), R4; \ 313 JMP (R4) 314 // Note: can't just "BR NAME(SB)" - bad inlining results. 315 316 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48 317 MOVWU frameSize+32(FP), R19 318 DISPATCH(runtime·call32, 32) 319 DISPATCH(runtime·call64, 64) 320 DISPATCH(runtime·call128, 128) 321 DISPATCH(runtime·call256, 256) 322 DISPATCH(runtime·call512, 512) 323 DISPATCH(runtime·call1024, 1024) 324 DISPATCH(runtime·call2048, 2048) 325 DISPATCH(runtime·call4096, 4096) 326 DISPATCH(runtime·call8192, 8192) 327 DISPATCH(runtime·call16384, 16384) 328 DISPATCH(runtime·call32768, 32768) 329 DISPATCH(runtime·call65536, 65536) 330 DISPATCH(runtime·call131072, 131072) 331 DISPATCH(runtime·call262144, 262144) 332 DISPATCH(runtime·call524288, 524288) 333 DISPATCH(runtime·call1048576, 1048576) 334 DISPATCH(runtime·call2097152, 2097152) 335 DISPATCH(runtime·call4194304, 4194304) 336 DISPATCH(runtime·call8388608, 8388608) 337 DISPATCH(runtime·call16777216, 16777216) 338 DISPATCH(runtime·call33554432, 33554432) 339 DISPATCH(runtime·call67108864, 67108864) 340 DISPATCH(runtime·call134217728, 134217728) 341 DISPATCH(runtime·call268435456, 268435456) 342 DISPATCH(runtime·call536870912, 536870912) 343 DISPATCH(runtime·call1073741824, 1073741824) 344 MOVV $runtime·badreflectcall(SB), R4 345 JMP (R4) 346 347 #define CALLFN(NAME,MAXSIZE) \ 348 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ 349 NO_LOCAL_POINTERS; \ 350 /* copy arguments to stack */ \ 351 MOVV arg+16(FP), R4; \ 352 MOVWU argsize+24(FP), R5; \ 353 MOVV R3, R12; \ 354 ADDV $8, R12; \ 355 ADDV R12, R5; \ 356 BEQ R12, R5, 6(PC); \ 357 MOVBU (R4), R6; \ 358 ADDV $1, R4; \ 359 MOVBU R6, (R12); \ 360 ADDV $1, R12; \ 361 JMP -5(PC); \ 362 /* set up argument registers */ \ 363 MOVV regArgs+40(FP), R25; \ 364 JAL ·unspillArgs(SB); \ 365 /* call function */ \ 366 MOVV f+8(FP), REGCTXT; \ 367 MOVV (REGCTXT), R25; \ 368 PCDATA $PCDATA_StackMapIndex, $0; \ 369 JAL (R25); \ 370 /* copy return values back */ \ 371 MOVV regArgs+40(FP), R25; \ 372 JAL ·spillArgs(SB); \ 373 MOVV argtype+0(FP), R7; \ 374 MOVV arg+16(FP), R4; \ 375 MOVWU n+24(FP), R5; \ 376 MOVWU retoffset+28(FP), R6; \ 377 ADDV $8, R3, R12; \ 378 ADDV R6, R12; \ 379 ADDV R6, R4; \ 380 SUBVU R6, R5; \ 381 JAL callRet<>(SB); \ 382 RET 383 384 // callRet copies return values back at the end of call*. This is a 385 // separate function so it can allocate stack space for the arguments 386 // to reflectcallmove. It does not follow the Go ABI; it expects its 387 // arguments in registers. 388 TEXT callRet<>(SB), NOSPLIT, $40-0 389 NO_LOCAL_POINTERS 390 MOVV R7, 8(R3) 391 MOVV R4, 16(R3) 392 MOVV R12, 24(R3) 393 MOVV R5, 32(R3) 394 MOVV R25, 40(R3) 395 JAL runtime·reflectcallmove(SB) 396 RET 397 398 CALLFN(·call16, 16) 399 CALLFN(·call32, 32) 400 CALLFN(·call64, 64) 401 CALLFN(·call128, 128) 402 CALLFN(·call256, 256) 403 CALLFN(·call512, 512) 404 CALLFN(·call1024, 1024) 405 CALLFN(·call2048, 2048) 406 CALLFN(·call4096, 4096) 407 CALLFN(·call8192, 8192) 408 CALLFN(·call16384, 16384) 409 CALLFN(·call32768, 32768) 410 CALLFN(·call65536, 65536) 411 CALLFN(·call131072, 131072) 412 CALLFN(·call262144, 262144) 413 CALLFN(·call524288, 524288) 414 CALLFN(·call1048576, 1048576) 415 CALLFN(·call2097152, 2097152) 416 CALLFN(·call4194304, 4194304) 417 CALLFN(·call8388608, 8388608) 418 CALLFN(·call16777216, 16777216) 419 CALLFN(·call33554432, 33554432) 420 CALLFN(·call67108864, 67108864) 421 CALLFN(·call134217728, 134217728) 422 CALLFN(·call268435456, 268435456) 423 CALLFN(·call536870912, 536870912) 424 CALLFN(·call1073741824, 1073741824) 425 426 TEXT runtime·procyield(SB),NOSPLIT,$0-0 427 RET 428 429 // Save state of caller into g->sched. 430 // but using fake PC from systemstack_switch. 431 // Must only be called from functions with no locals ($0) 432 // or else unwinding from systemstack_switch is incorrect. 433 // Smashes R19. 434 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0 435 MOVV $runtime·systemstack_switch(SB), R19 436 ADDV $8, R19 437 MOVV R19, (g_sched+gobuf_pc)(g) 438 MOVV R3, (g_sched+gobuf_sp)(g) 439 MOVV R0, (g_sched+gobuf_lr)(g) 440 MOVV R0, (g_sched+gobuf_ret)(g) 441 // Assert ctxt is zero. See func save. 442 MOVV (g_sched+gobuf_ctxt)(g), R19 443 BEQ R19, 2(PC) 444 JAL runtime·abort(SB) 445 RET 446 447 // func asmcgocall(fn, arg unsafe.Pointer) int32 448 // Call fn(arg) on the scheduler stack, 449 // aligned appropriately for the gcc ABI. 450 // See cgocall.go for more details. 451 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 452 MOVV fn+0(FP), R25 453 MOVV arg+8(FP), R4 454 455 MOVV R3, R12 // save original stack pointer 456 MOVV g, R13 457 458 // Figure out if we need to switch to m->g0 stack. 459 // We get called to create new OS threads too, and those 460 // come in on the m->g0 stack already. 461 MOVV g_m(g), R5 462 MOVV m_gsignal(R5), R6 463 BEQ R6, g, g0 464 MOVV m_g0(R5), R6 465 BEQ R6, g, g0 466 467 JAL gosave_systemstack_switch<>(SB) 468 MOVV R6, g 469 JAL runtime·save_g(SB) 470 MOVV (g_sched+gobuf_sp)(g), R3 471 472 // Now on a scheduling stack (a pthread-created stack). 473 g0: 474 // Save room for two of our pointers. 475 ADDV $-16, R3 476 MOVV R13, 0(R3) // save old g on stack 477 MOVV (g_stack+stack_hi)(R13), R13 478 SUBVU R12, R13 479 MOVV R13, 8(R3) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 480 JAL (R25) 481 482 // Restore g, stack pointer. R4 is return value. 483 MOVV 0(R3), g 484 JAL runtime·save_g(SB) 485 MOVV (g_stack+stack_hi)(g), R5 486 MOVV 8(R3), R6 487 SUBVU R6, R5 488 MOVV R5, R3 489 490 MOVW R4, ret+16(FP) 491 RET 492 493 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) 494 // See cgocall.go for more details. 495 TEXT ·cgocallback(SB),NOSPLIT,$24-24 496 NO_LOCAL_POINTERS 497 498 // Skip cgocallbackg, just dropm when fn is nil, and frame is the saved g. 499 // It is used to dropm while thread is exiting. 500 MOVV fn+0(FP), R5 501 BNE R5, loadg 502 // Restore the g from frame. 503 MOVV frame+8(FP), g 504 JMP dropm 505 506 loadg: 507 // Load m and g from thread-local storage. 508 MOVB runtime·iscgo(SB), R19 509 BEQ R19, nocgo 510 JAL runtime·load_g(SB) 511 nocgo: 512 513 // If g is nil, Go did not create the current thread, 514 // or if this thread never called into Go on pthread platforms. 515 // Call needm to obtain one for temporary use. 516 // In this case, we're running on the thread stack, so there's 517 // lots of space, but the linker doesn't know. Hide the call from 518 // the linker analysis by using an indirect call. 519 BEQ g, needm 520 521 MOVV g_m(g), R12 522 MOVV R12, savedm-8(SP) 523 JMP havem 524 525 needm: 526 MOVV g, savedm-8(SP) // g is zero, so is m. 527 MOVV $runtime·needAndBindM(SB), R4 528 JAL (R4) 529 530 // Set m->sched.sp = SP, so that if a panic happens 531 // during the function we are about to execute, it will 532 // have a valid SP to run on the g0 stack. 533 // The next few lines (after the havem label) 534 // will save this SP onto the stack and then write 535 // the same SP back to m->sched.sp. That seems redundant, 536 // but if an unrecovered panic happens, unwindm will 537 // restore the g->sched.sp from the stack location 538 // and then systemstack will try to use it. If we don't set it here, 539 // that restored SP will be uninitialized (typically 0) and 540 // will not be usable. 541 MOVV g_m(g), R12 542 MOVV m_g0(R12), R19 543 MOVV R3, (g_sched+gobuf_sp)(R19) 544 545 havem: 546 // Now there's a valid m, and we're running on its m->g0. 547 // Save current m->g0->sched.sp on stack and then set it to SP. 548 // Save current sp in m->g0->sched.sp in preparation for 549 // switch back to m->curg stack. 550 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP). 551 MOVV m_g0(R12), R19 552 MOVV (g_sched+gobuf_sp)(R19), R13 553 MOVV R13, savedsp-24(SP) // must match frame size 554 MOVV R3, (g_sched+gobuf_sp)(R19) 555 556 // Switch to m->curg stack and call runtime.cgocallbackg. 557 // Because we are taking over the execution of m->curg 558 // but *not* resuming what had been running, we need to 559 // save that information (m->curg->sched) so we can restore it. 560 // We can restore m->curg->sched.sp easily, because calling 561 // runtime.cgocallbackg leaves SP unchanged upon return. 562 // To save m->curg->sched.pc, we push it onto the stack. 563 // This has the added benefit that it looks to the traceback 564 // routine like cgocallbackg is going to return to that 565 // PC (because the frame we allocate below has the same 566 // size as cgocallback_gofunc's frame declared above) 567 // so that the traceback will seamlessly trace back into 568 // the earlier calls. 569 MOVV m_curg(R12), g 570 JAL runtime·save_g(SB) 571 MOVV (g_sched+gobuf_sp)(g), R13 // prepare stack as R13 572 MOVV (g_sched+gobuf_pc)(g), R4 573 MOVV R4, -(24+8)(R13) // "saved LR"; must match frame size 574 MOVV fn+0(FP), R5 575 MOVV frame+8(FP), R6 576 MOVV ctxt+16(FP), R7 577 MOVV $-(24+8)(R13), R3 578 MOVV R5, 8(R3) 579 MOVV R6, 16(R3) 580 MOVV R7, 24(R3) 581 JAL runtime·cgocallbackg(SB) 582 583 // Restore g->sched (== m->curg->sched) from saved values. 584 MOVV 0(R3), R4 585 MOVV R4, (g_sched+gobuf_pc)(g) 586 MOVV $(24+8)(R3), R13 // must match frame size 587 MOVV R13, (g_sched+gobuf_sp)(g) 588 589 // Switch back to m->g0's stack and restore m->g0->sched.sp. 590 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 591 // so we do not have to restore it.) 592 MOVV g_m(g), R12 593 MOVV m_g0(R12), g 594 JAL runtime·save_g(SB) 595 MOVV (g_sched+gobuf_sp)(g), R3 596 MOVV savedsp-24(SP), R13 // must match frame size 597 MOVV R13, (g_sched+gobuf_sp)(g) 598 599 // If the m on entry was nil, we called needm above to borrow an m, 600 // 1. for the duration of the call on non-pthread platforms, 601 // 2. or the duration of the C thread alive on pthread platforms. 602 // If the m on entry wasn't nil, 603 // 1. the thread might be a Go thread, 604 // 2. or it wasn't the first call from a C thread on pthread platforms, 605 // since then we skip dropm to resue the m in the first call. 606 MOVV savedm-8(SP), R12 607 BNE R12, droppedm 608 609 // Skip dropm to reuse it in the next call, when a pthread key has been created. 610 MOVV _cgo_pthread_key_created(SB), R12 611 // It means cgo is disabled when _cgo_pthread_key_created is a nil pointer, need dropm. 612 BEQ R12, dropm 613 MOVV (R12), R12 614 BNE R12, droppedm 615 616 dropm: 617 MOVV $runtime·dropm(SB), R4 618 JAL (R4) 619 droppedm: 620 621 // Done! 622 RET 623 624 // void setg(G*); set g. for use by needm. 625 TEXT runtime·setg(SB), NOSPLIT, $0-8 626 MOVV gg+0(FP), g 627 // This only happens if iscgo, so jump straight to save_g 628 JAL runtime·save_g(SB) 629 RET 630 631 // void setg_gcc(G*); set g called from gcc with g in R19 632 TEXT setg_gcc<>(SB),NOSPLIT,$0-0 633 MOVV R19, g 634 JAL runtime·save_g(SB) 635 RET 636 637 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 638 MOVW (R0), R0 639 UNDEF 640 641 // AES hashing not implemented for loong64 642 TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32 643 JMP runtime·memhashFallback<ABIInternal>(SB) 644 TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 645 JMP runtime·strhashFallback<ABIInternal>(SB) 646 TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 647 JMP runtime·memhash32Fallback<ABIInternal>(SB) 648 TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 649 JMP runtime·memhash64Fallback<ABIInternal>(SB) 650 651 TEXT runtime·return0(SB), NOSPLIT, $0 652 MOVW $0, R19 653 RET 654 655 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 656 // Must obey the gcc calling convention. 657 TEXT _cgo_topofstack(SB),NOSPLIT,$16 658 // g (R22) and REGTMP (R30) might be clobbered by load_g. They 659 // are callee-save in the gcc calling convention, so save them. 660 MOVV R30, savedREGTMP-16(SP) 661 MOVV g, savedG-8(SP) 662 663 JAL runtime·load_g(SB) 664 MOVV g_m(g), R19 665 MOVV m_curg(R19), R19 666 MOVV (g_stack+stack_hi)(R19), R4 // return value in R4 667 668 MOVV savedG-8(SP), g 669 MOVV savedREGTMP-16(SP), R30 670 RET 671 672 // The top-most function running on a goroutine 673 // returns to goexit+PCQuantum. 674 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 675 NOOP 676 JAL runtime·goexit1(SB) // does not return 677 // traceback from goexit1 must hit code range of goexit 678 NOOP 679 680 // This is called from .init_array and follows the platform, not Go, ABI. 681 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 682 ADDV $-0x10, R3 683 MOVV R30, 8(R3) // The access to global variables below implicitly uses R30, which is callee-save 684 MOVV runtime·lastmoduledatap(SB), R12 685 MOVV R4, moduledata_next(R12) 686 MOVV R4, runtime·lastmoduledatap(SB) 687 MOVV 8(R3), R30 688 ADDV $0x10, R3 689 RET 690 691 TEXT ·checkASM(SB),NOSPLIT,$0-1 692 MOVW $1, R19 693 MOVB R19, ret+0(FP) 694 RET 695 696 #ifdef GOEXPERIMENT_regabiargs 697 // spillArgs stores return values from registers to a *internal/abi.RegArgs in R25. 698 TEXT ·spillArgs(SB),NOSPLIT,$0-0 699 MOVV R4, (0*8)(R25) 700 MOVV R5, (1*8)(R25) 701 MOVV R6, (2*8)(R25) 702 MOVV R7, (3*8)(R25) 703 MOVV R8, (4*8)(R25) 704 MOVV R9, (5*8)(R25) 705 MOVV R10, (6*8)(R25) 706 MOVV R11, (7*8)(R25) 707 MOVV R12, (8*8)(R25) 708 MOVV R13, (9*8)(R25) 709 MOVV R14, (10*8)(R25) 710 MOVV R15, (11*8)(R25) 711 MOVV R16, (12*8)(R25) 712 MOVV R17, (13*8)(R25) 713 MOVV R18, (14*8)(R25) 714 MOVV R19, (15*8)(R25) 715 MOVD F0, (16*8)(R25) 716 MOVD F1, (17*8)(R25) 717 MOVD F2, (18*8)(R25) 718 MOVD F3, (19*8)(R25) 719 MOVD F4, (20*8)(R25) 720 MOVD F5, (21*8)(R25) 721 MOVD F6, (22*8)(R25) 722 MOVD F7, (23*8)(R25) 723 MOVD F8, (24*8)(R25) 724 MOVD F9, (25*8)(R25) 725 MOVD F10, (26*8)(R25) 726 MOVD F11, (27*8)(R25) 727 MOVD F12, (28*8)(R25) 728 MOVD F13, (29*8)(R25) 729 MOVD F14, (30*8)(R25) 730 MOVD F15, (31*8)(R25) 731 RET 732 733 // unspillArgs loads args into registers from a *internal/abi.RegArgs in R25. 734 TEXT ·unspillArgs(SB),NOSPLIT,$0-0 735 MOVV (0*8)(R25), R4 736 MOVV (1*8)(R25), R5 737 MOVV (2*8)(R25), R6 738 MOVV (3*8)(R25), R7 739 MOVV (4*8)(R25), R8 740 MOVV (5*8)(R25), R9 741 MOVV (6*8)(R25), R10 742 MOVV (7*8)(R25), R11 743 MOVV (8*8)(R25), R12 744 MOVV (9*8)(R25), R13 745 MOVV (10*8)(R25), R14 746 MOVV (11*8)(R25), R15 747 MOVV (12*8)(R25), R16 748 MOVV (13*8)(R25), R17 749 MOVV (14*8)(R25), R18 750 MOVV (15*8)(R25), R19 751 MOVD (16*8)(R25), F0 752 MOVD (17*8)(R25), F1 753 MOVD (18*8)(R25), F2 754 MOVD (19*8)(R25), F3 755 MOVD (20*8)(R25), F4 756 MOVD (21*8)(R25), F5 757 MOVD (22*8)(R25), F6 758 MOVD (23*8)(R25), F7 759 MOVD (24*8)(R25), F8 760 MOVD (25*8)(R25), F9 761 MOVD (26*8)(R25), F10 762 MOVD (27*8)(R25), F11 763 MOVD (28*8)(R25), F12 764 MOVD (29*8)(R25), F13 765 MOVD (30*8)(R25), F14 766 MOVD (31*8)(R25), F15 767 RET 768 #else 769 TEXT ·spillArgs(SB),NOSPLIT,$0-0 770 RET 771 772 TEXT ·unspillArgs(SB),NOSPLIT,$0-0 773 RET 774 #endif 775 776 // gcWriteBarrier informs the GC about heap pointer writes. 777 // 778 // gcWriteBarrier does NOT follow the Go ABI. It accepts the 779 // number of bytes of buffer needed in R29, and returns a pointer 780 // to the buffer space in R29. 781 // It clobbers R30 (the linker temp register). 782 // The act of CALLing gcWriteBarrier will clobber R1 (LR). 783 // It does not clobber any other general-purpose registers, 784 // but may clobber others (e.g., floating point registers). 785 TEXT gcWriteBarrier<>(SB),NOSPLIT,$216 786 // Save the registers clobbered by the fast path. 787 MOVV R19, 208(R3) 788 MOVV R13, 216(R3) 789 retry: 790 MOVV g_m(g), R19 791 MOVV m_p(R19), R19 792 MOVV (p_wbBuf+wbBuf_next)(R19), R13 793 MOVV (p_wbBuf+wbBuf_end)(R19), R30 // R30 is linker temp register 794 // Increment wbBuf.next position. 795 ADDV R29, R13 796 // Is the buffer full? 797 BLTU R30, R13, flush 798 // Commit to the larger buffer. 799 MOVV R13, (p_wbBuf+wbBuf_next)(R19) 800 // Make return value (the original next position) 801 SUBV R29, R13, R29 802 // Restore registers. 803 MOVV 208(R3), R19 804 MOVV 216(R3), R13 805 RET 806 807 flush: 808 // Save all general purpose registers since these could be 809 // clobbered by wbBufFlush and were not saved by the caller. 810 MOVV R27, 8(R3) 811 MOVV R28, 16(R3) 812 // R1 is LR, which was saved by the prologue. 813 MOVV R2, 24(R3) 814 // R3 is SP. 815 MOVV R4, 32(R3) 816 MOVV R5, 40(R3) 817 MOVV R6, 48(R3) 818 MOVV R7, 56(R3) 819 MOVV R8, 64(R3) 820 MOVV R9, 72(R3) 821 MOVV R10, 80(R3) 822 MOVV R11, 88(R3) 823 MOVV R12, 96(R3) 824 // R13 already saved 825 MOVV R14, 104(R3) 826 MOVV R15, 112(R3) 827 MOVV R16, 120(R3) 828 MOVV R17, 128(R3) 829 MOVV R18, 136(R3) 830 // R19 already saved 831 MOVV R20, 144(R3) 832 MOVV R21, 152(R3) 833 // R22 is g. 834 MOVV R23, 160(R3) 835 MOVV R24, 168(R3) 836 MOVV R25, 176(R3) 837 MOVV R26, 184(R3) 838 // R27 already saved 839 // R28 already saved. 840 MOVV R29, 192(R3) 841 // R30 is tmp register. 842 MOVV R31, 200(R3) 843 844 CALL runtime·wbBufFlush(SB) 845 846 MOVV 8(R3), R27 847 MOVV 16(R3), R28 848 MOVV 24(R3), R2 849 MOVV 32(R3), R4 850 MOVV 40(R3), R5 851 MOVV 48(R3), R6 852 MOVV 56(R3), R7 853 MOVV 64(R3), R8 854 MOVV 72(R3), R9 855 MOVV 80(R3), R10 856 MOVV 88(R3), R11 857 MOVV 96(R3), R12 858 MOVV 104(R3), R14 859 MOVV 112(R3), R15 860 MOVV 120(R3), R16 861 MOVV 128(R3), R17 862 MOVV 136(R3), R18 863 MOVV 144(R3), R20 864 MOVV 152(R3), R21 865 MOVV 160(R3), R23 866 MOVV 168(R3), R24 867 MOVV 176(R3), R25 868 MOVV 184(R3), R26 869 MOVV 192(R3), R29 870 MOVV 200(R3), R31 871 JMP retry 872 873 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0 874 MOVV $8, R29 875 JMP gcWriteBarrier<>(SB) 876 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0 877 MOVV $16, R29 878 JMP gcWriteBarrier<>(SB) 879 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0 880 MOVV $24, R29 881 JMP gcWriteBarrier<>(SB) 882 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0 883 MOVV $32, R29 884 JMP gcWriteBarrier<>(SB) 885 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0 886 MOVV $40, R29 887 JMP gcWriteBarrier<>(SB) 888 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0 889 MOVV $48, R29 890 JMP gcWriteBarrier<>(SB) 891 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0 892 MOVV $56, R29 893 JMP gcWriteBarrier<>(SB) 894 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0 895 MOVV $64, R29 896 JMP gcWriteBarrier<>(SB) 897 898 // Note: these functions use a special calling convention to save generated code space. 899 // Arguments are passed in registers, but the space for those arguments are allocated 900 // in the caller's stack frame. These stubs write the args into that stack space and 901 // then tail call to the corresponding runtime handler. 902 // The tail call makes these stubs disappear in backtraces. 903 TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16 904 #ifdef GOEXPERIMENT_regabiargs 905 MOVV R20, R4 906 MOVV R21, R5 907 #else 908 MOVV R20, x+0(FP) 909 MOVV R21, y+8(FP) 910 #endif 911 JMP runtime·goPanicIndex<ABIInternal>(SB) 912 TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16 913 #ifdef GOEXPERIMENT_regabiargs 914 MOVV R20, R4 915 MOVV R21, R5 916 #else 917 MOVV R20, x+0(FP) 918 MOVV R21, y+8(FP) 919 #endif 920 JMP runtime·goPanicIndexU<ABIInternal>(SB) 921 TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16 922 #ifdef GOEXPERIMENT_regabiargs 923 MOVV R21, R4 924 MOVV R23, R5 925 #else 926 MOVV R21, x+0(FP) 927 MOVV R23, y+8(FP) 928 #endif 929 JMP runtime·goPanicSliceAlen<ABIInternal>(SB) 930 TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16 931 #ifdef GOEXPERIMENT_regabiargs 932 MOVV R21, R4 933 MOVV R23, R5 934 #else 935 MOVV R21, x+0(FP) 936 MOVV R23, y+8(FP) 937 #endif 938 JMP runtime·goPanicSliceAlenU<ABIInternal>(SB) 939 TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16 940 #ifdef GOEXPERIMENT_regabiargs 941 MOVV R21, R4 942 MOVV R23, R5 943 #else 944 MOVV R21, x+0(FP) 945 MOVV R23, y+8(FP) 946 #endif 947 JMP runtime·goPanicSliceAcap<ABIInternal>(SB) 948 TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16 949 #ifdef GOEXPERIMENT_regabiargs 950 MOVV R21, R4 951 MOVV R23, R5 952 #else 953 MOVV R21, x+0(FP) 954 MOVV R23, y+8(FP) 955 #endif 956 JMP runtime·goPanicSliceAcapU<ABIInternal>(SB) 957 TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16 958 #ifdef GOEXPERIMENT_regabiargs 959 MOVV R20, R4 960 MOVV R21, R5 961 #else 962 MOVV R20, x+0(FP) 963 MOVV R21, y+8(FP) 964 #endif 965 JMP runtime·goPanicSliceB<ABIInternal>(SB) 966 TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16 967 #ifdef GOEXPERIMENT_regabiargs 968 MOVV R20, R4 969 MOVV R21, R5 970 #else 971 MOVV R20, x+0(FP) 972 MOVV R21, y+8(FP) 973 #endif 974 JMP runtime·goPanicSliceBU<ABIInternal>(SB) 975 TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16 976 #ifdef GOEXPERIMENT_regabiargs 977 MOVV R23, R4 978 MOVV R24, R5 979 #else 980 MOVV R23, x+0(FP) 981 MOVV R24, y+8(FP) 982 #endif 983 JMP runtime·goPanicSlice3Alen<ABIInternal>(SB) 984 TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16 985 #ifdef GOEXPERIMENT_regabiargs 986 MOVV R23, R4 987 MOVV R24, R5 988 #else 989 MOVV R23, x+0(FP) 990 MOVV R24, y+8(FP) 991 #endif 992 JMP runtime·goPanicSlice3AlenU<ABIInternal>(SB) 993 TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16 994 #ifdef GOEXPERIMENT_regabiargs 995 MOVV R23, R4 996 MOVV R24, R5 997 #else 998 MOVV R23, x+0(FP) 999 MOVV R24, y+8(FP) 1000 #endif 1001 JMP runtime·goPanicSlice3Acap<ABIInternal>(SB) 1002 TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16 1003 #ifdef GOEXPERIMENT_regabiargs 1004 MOVV R23, R4 1005 MOVV R24, R5 1006 #else 1007 MOVV R23, x+0(FP) 1008 MOVV R24, y+8(FP) 1009 #endif 1010 JMP runtime·goPanicSlice3AcapU<ABIInternal>(SB) 1011 TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16 1012 #ifdef GOEXPERIMENT_regabiargs 1013 MOVV R21, R4 1014 MOVV R23, R5 1015 #else 1016 MOVV R21, x+0(FP) 1017 MOVV R23, y+8(FP) 1018 #endif 1019 JMP runtime·goPanicSlice3B<ABIInternal>(SB) 1020 TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16 1021 #ifdef GOEXPERIMENT_regabiargs 1022 MOVV R21, R4 1023 MOVV R23, R5 1024 #else 1025 MOVV R21, x+0(FP) 1026 MOVV R23, y+8(FP) 1027 #endif 1028 JMP runtime·goPanicSlice3BU<ABIInternal>(SB) 1029 TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16 1030 #ifdef GOEXPERIMENT_regabiargs 1031 MOVV R20, R4 1032 MOVV R21, R5 1033 #else 1034 MOVV R20, x+0(FP) 1035 MOVV R21, y+8(FP) 1036 #endif 1037 JMP runtime·goPanicSlice3C<ABIInternal>(SB) 1038 TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16 1039 #ifdef GOEXPERIMENT_regabiargs 1040 MOVV R20, R4 1041 MOVV R21, R5 1042 #else 1043 MOVV R20, x+0(FP) 1044 MOVV R21, y+8(FP) 1045 #endif 1046 JMP runtime·goPanicSlice3CU<ABIInternal>(SB) 1047 TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16 1048 #ifdef GOEXPERIMENT_regabiargs 1049 MOVV R23, R4 1050 MOVV R24, R5 1051 #else 1052 MOVV R23, x+0(FP) 1053 MOVV R24, y+8(FP) 1054 #endif 1055 JMP runtime·goPanicSliceConvert<ABIInternal>(SB)