github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/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(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(SB), NOSPLIT|NOFRAME, $0-8 127 // Save caller state in g->sched 128 MOVV R3, (g_sched+gobuf_sp)(g) 129 MOVV R1, (g_sched+gobuf_pc)(g) 130 MOVV R0, (g_sched+gobuf_lr)(g) 131 132 // Switch to m->g0 & its stack, call fn. 133 MOVV g, R19 134 MOVV g_m(g), R4 135 MOVV m_g0(R4), g 136 JAL runtime·save_g(SB) 137 BNE g, R19, 2(PC) 138 JMP runtime·badmcall(SB) 139 MOVV fn+0(FP), REGCTXT // context 140 MOVV 0(REGCTXT), R5 // code pointer 141 MOVV (g_sched+gobuf_sp)(g), R3 // sp = m->g0->sched.sp 142 ADDV $-16, R3 143 MOVV R19, 8(R3) 144 MOVV R0, 0(R3) 145 JAL (R5) 146 JMP runtime·badmcall2(SB) 147 148 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 149 // of the G stack. We need to distinguish the routine that 150 // lives at the bottom of the G stack from the one that lives 151 // at the top of the system stack because the one at the top of 152 // the system stack terminates the stack walk (see topofstack()). 153 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 154 UNDEF 155 JAL (R1) // make sure this function is not leaf 156 RET 157 158 // func systemstack(fn func()) 159 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 160 MOVV fn+0(FP), R19 // R19 = fn 161 MOVV R19, REGCTXT // context 162 MOVV g_m(g), R4 // R4 = m 163 164 MOVV m_gsignal(R4), R5 // R5 = gsignal 165 BEQ g, R5, noswitch 166 167 MOVV m_g0(R4), R5 // R5 = g0 168 BEQ g, R5, noswitch 169 170 MOVV m_curg(R4), R6 171 BEQ g, R6, switch 172 173 // Bad: g is not gsignal, not g0, not curg. What is it? 174 // Hide call from linker nosplit analysis. 175 MOVV $runtime·badsystemstack(SB), R7 176 JAL (R7) 177 JAL runtime·abort(SB) 178 179 switch: 180 // save our state in g->sched. Pretend to 181 // be systemstack_switch if the G stack is scanned. 182 JAL gosave_systemstack_switch<>(SB) 183 184 // switch to g0 185 MOVV R5, g 186 JAL runtime·save_g(SB) 187 MOVV (g_sched+gobuf_sp)(g), R19 188 MOVV R19, R3 189 190 // call target function 191 MOVV 0(REGCTXT), R6 // code pointer 192 JAL (R6) 193 194 // switch back to g 195 MOVV g_m(g), R4 196 MOVV m_curg(R4), g 197 JAL runtime·save_g(SB) 198 MOVV (g_sched+gobuf_sp)(g), R3 199 MOVV R0, (g_sched+gobuf_sp)(g) 200 RET 201 202 noswitch: 203 // already on m stack, just call directly 204 // Using a tail call here cleans up tracebacks since we won't stop 205 // at an intermediate systemstack. 206 MOVV 0(REGCTXT), R4 // code pointer 207 MOVV 0(R3), R1 // restore LR 208 ADDV $8, R3 209 JMP (R4) 210 211 /* 212 * support for morestack 213 */ 214 215 // Called during function prolog when more stack is needed. 216 // Caller has already loaded: 217 // loong64: R5: LR 218 // 219 // The traceback routines see morestack on a g0 as being 220 // the top of a stack (for example, morestack calling newstack 221 // calling the scheduler calling newm calling gc), so we must 222 // record an argument size. For that purpose, it has no arguments. 223 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 224 // Cannot grow scheduler stack (m->g0). 225 MOVV g_m(g), R7 226 MOVV m_g0(R7), R8 227 BNE g, R8, 3(PC) 228 JAL runtime·badmorestackg0(SB) 229 JAL runtime·abort(SB) 230 231 // Cannot grow signal stack (m->gsignal). 232 MOVV m_gsignal(R7), R8 233 BNE g, R8, 3(PC) 234 JAL runtime·badmorestackgsignal(SB) 235 JAL runtime·abort(SB) 236 237 // Called from f. 238 // Set g->sched to context in f. 239 MOVV R3, (g_sched+gobuf_sp)(g) 240 MOVV R1, (g_sched+gobuf_pc)(g) 241 MOVV R5, (g_sched+gobuf_lr)(g) 242 MOVV REGCTXT, (g_sched+gobuf_ctxt)(g) 243 244 // Called from f. 245 // Set m->morebuf to f's caller. 246 MOVV R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 247 MOVV R3, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 248 MOVV g, (m_morebuf+gobuf_g)(R7) 249 250 // Call newstack on m->g0's stack. 251 MOVV m_g0(R7), g 252 JAL runtime·save_g(SB) 253 MOVV (g_sched+gobuf_sp)(g), R3 254 // Create a stack frame on g0 to call newstack. 255 MOVV R0, -8(R3) // Zero saved LR in frame 256 ADDV $-8, R3 257 JAL runtime·newstack(SB) 258 259 // Not reached, but make sure the return PC from the call to newstack 260 // is still in this function, and not the beginning of the next. 261 UNDEF 262 263 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 264 // Force SPWRITE. This function doesn't actually write SP, 265 // but it is called with a special calling convention where 266 // the caller doesn't save LR on stack but passes it as a 267 // register (R5), and the unwinder currently doesn't understand. 268 // Make it SPWRITE to stop unwinding. (See issue 54332) 269 MOVV R3, R3 270 271 MOVV R0, REGCTXT 272 JMP runtime·morestack(SB) 273 274 // reflectcall: call a function with the given argument list 275 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 276 // we don't have variable-sized frames, so we use a small number 277 // of constant-sized-frame functions to encode a few bits of size in the pc. 278 // Caution: ugly multiline assembly macros in your future! 279 280 #define DISPATCH(NAME,MAXSIZE) \ 281 MOVV $MAXSIZE, R30; \ 282 SGTU R19, R30, R30; \ 283 BNE R30, 3(PC); \ 284 MOVV $NAME(SB), R4; \ 285 JMP (R4) 286 // Note: can't just "BR NAME(SB)" - bad inlining results. 287 288 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48 289 MOVWU stackArgsSize+24(FP), R19 290 DISPATCH(runtime·call32, 32) 291 DISPATCH(runtime·call64, 64) 292 DISPATCH(runtime·call128, 128) 293 DISPATCH(runtime·call256, 256) 294 DISPATCH(runtime·call512, 512) 295 DISPATCH(runtime·call1024, 1024) 296 DISPATCH(runtime·call2048, 2048) 297 DISPATCH(runtime·call4096, 4096) 298 DISPATCH(runtime·call8192, 8192) 299 DISPATCH(runtime·call16384, 16384) 300 DISPATCH(runtime·call32768, 32768) 301 DISPATCH(runtime·call65536, 65536) 302 DISPATCH(runtime·call131072, 131072) 303 DISPATCH(runtime·call262144, 262144) 304 DISPATCH(runtime·call524288, 524288) 305 DISPATCH(runtime·call1048576, 1048576) 306 DISPATCH(runtime·call2097152, 2097152) 307 DISPATCH(runtime·call4194304, 4194304) 308 DISPATCH(runtime·call8388608, 8388608) 309 DISPATCH(runtime·call16777216, 16777216) 310 DISPATCH(runtime·call33554432, 33554432) 311 DISPATCH(runtime·call67108864, 67108864) 312 DISPATCH(runtime·call134217728, 134217728) 313 DISPATCH(runtime·call268435456, 268435456) 314 DISPATCH(runtime·call536870912, 536870912) 315 DISPATCH(runtime·call1073741824, 1073741824) 316 MOVV $runtime·badreflectcall(SB), R4 317 JMP (R4) 318 319 #define CALLFN(NAME,MAXSIZE) \ 320 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 321 NO_LOCAL_POINTERS; \ 322 /* copy arguments to stack */ \ 323 MOVV arg+16(FP), R4; \ 324 MOVWU argsize+24(FP), R5; \ 325 MOVV R3, R12; \ 326 ADDV $8, R12; \ 327 ADDV R12, R5; \ 328 BEQ R12, R5, 6(PC); \ 329 MOVBU (R4), R6; \ 330 ADDV $1, R4; \ 331 MOVBU R6, (R12); \ 332 ADDV $1, R12; \ 333 JMP -5(PC); \ 334 /* call function */ \ 335 MOVV f+8(FP), REGCTXT; \ 336 MOVV (REGCTXT), R6; \ 337 PCDATA $PCDATA_StackMapIndex, $0; \ 338 JAL (R6); \ 339 /* copy return values back */ \ 340 MOVV argtype+0(FP), R7; \ 341 MOVV arg+16(FP), R4; \ 342 MOVWU n+24(FP), R5; \ 343 MOVWU retoffset+28(FP), R6; \ 344 ADDV $8, R3, R12; \ 345 ADDV R6, R12; \ 346 ADDV R6, R4; \ 347 SUBVU R6, R5; \ 348 JAL callRet<>(SB); \ 349 RET 350 351 // callRet copies return values back at the end of call*. This is a 352 // separate function so it can allocate stack space for the arguments 353 // to reflectcallmove. It does not follow the Go ABI; it expects its 354 // arguments in registers. 355 TEXT callRet<>(SB), NOSPLIT, $32-0 356 MOVV R7, 8(R3) 357 MOVV R4, 16(R3) 358 MOVV R12, 24(R3) 359 MOVV R5, 32(R3) 360 JAL runtime·reflectcallmove(SB) 361 RET 362 363 CALLFN(·call16, 16) 364 CALLFN(·call32, 32) 365 CALLFN(·call64, 64) 366 CALLFN(·call128, 128) 367 CALLFN(·call256, 256) 368 CALLFN(·call512, 512) 369 CALLFN(·call1024, 1024) 370 CALLFN(·call2048, 2048) 371 CALLFN(·call4096, 4096) 372 CALLFN(·call8192, 8192) 373 CALLFN(·call16384, 16384) 374 CALLFN(·call32768, 32768) 375 CALLFN(·call65536, 65536) 376 CALLFN(·call131072, 131072) 377 CALLFN(·call262144, 262144) 378 CALLFN(·call524288, 524288) 379 CALLFN(·call1048576, 1048576) 380 CALLFN(·call2097152, 2097152) 381 CALLFN(·call4194304, 4194304) 382 CALLFN(·call8388608, 8388608) 383 CALLFN(·call16777216, 16777216) 384 CALLFN(·call33554432, 33554432) 385 CALLFN(·call67108864, 67108864) 386 CALLFN(·call134217728, 134217728) 387 CALLFN(·call268435456, 268435456) 388 CALLFN(·call536870912, 536870912) 389 CALLFN(·call1073741824, 1073741824) 390 391 TEXT runtime·procyield(SB),NOSPLIT,$0-0 392 RET 393 394 // Save state of caller into g->sched. 395 // but using fake PC from systemstack_switch. 396 // Must only be called from functions with no locals ($0) 397 // or else unwinding from systemstack_switch is incorrect. 398 // Smashes R19. 399 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0 400 MOVV $runtime·systemstack_switch(SB), R19 401 ADDV $8, R19 402 MOVV R19, (g_sched+gobuf_pc)(g) 403 MOVV R3, (g_sched+gobuf_sp)(g) 404 MOVV R0, (g_sched+gobuf_lr)(g) 405 MOVV R0, (g_sched+gobuf_ret)(g) 406 // Assert ctxt is zero. See func save. 407 MOVV (g_sched+gobuf_ctxt)(g), R19 408 BEQ R19, 2(PC) 409 JAL runtime·abort(SB) 410 RET 411 412 // func asmcgocall(fn, arg unsafe.Pointer) int32 413 // Call fn(arg) on the scheduler stack, 414 // aligned appropriately for the gcc ABI. 415 // See cgocall.go for more details. 416 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 417 MOVV fn+0(FP), R25 418 MOVV arg+8(FP), R4 419 420 MOVV R3, R12 // save original stack pointer 421 MOVV g, R13 422 423 // Figure out if we need to switch to m->g0 stack. 424 // We get called to create new OS threads too, and those 425 // come in on the m->g0 stack already. 426 MOVV g_m(g), R5 427 MOVV m_gsignal(R5), R6 428 BEQ R6, g, g0 429 MOVV m_g0(R5), R6 430 BEQ R6, g, g0 431 432 JAL gosave_systemstack_switch<>(SB) 433 MOVV R6, g 434 JAL runtime·save_g(SB) 435 MOVV (g_sched+gobuf_sp)(g), R3 436 437 // Now on a scheduling stack (a pthread-created stack). 438 g0: 439 // Save room for two of our pointers. 440 ADDV $-16, R3 441 MOVV R13, 0(R3) // save old g on stack 442 MOVV (g_stack+stack_hi)(R13), R13 443 SUBVU R12, R13 444 MOVV R13, 8(R3) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 445 JAL (R25) 446 447 // Restore g, stack pointer. R4 is return value. 448 MOVV 0(R3), g 449 JAL runtime·save_g(SB) 450 MOVV (g_stack+stack_hi)(g), R5 451 MOVV 8(R3), R6 452 SUBVU R6, R5 453 MOVV R5, R3 454 455 MOVW R4, ret+16(FP) 456 RET 457 458 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) 459 // See cgocall.go for more details. 460 TEXT ·cgocallback(SB),NOSPLIT,$24-24 461 NO_LOCAL_POINTERS 462 463 // Load m and g from thread-local storage. 464 MOVB runtime·iscgo(SB), R19 465 BEQ R19, nocgo 466 JAL runtime·load_g(SB) 467 nocgo: 468 469 // If g is nil, Go did not create the current thread. 470 // Call needm to obtain one for temporary use. 471 // In this case, we're running on the thread stack, so there's 472 // lots of space, but the linker doesn't know. Hide the call from 473 // the linker analysis by using an indirect call. 474 BEQ g, needm 475 476 MOVV g_m(g), R12 477 MOVV R12, savedm-8(SP) 478 JMP havem 479 480 needm: 481 MOVV g, savedm-8(SP) // g is zero, so is m. 482 MOVV $runtime·needm(SB), R4 483 JAL (R4) 484 485 // Set m->sched.sp = SP, so that if a panic happens 486 // during the function we are about to execute, it will 487 // have a valid SP to run on the g0 stack. 488 // The next few lines (after the havem label) 489 // will save this SP onto the stack and then write 490 // the same SP back to m->sched.sp. That seems redundant, 491 // but if an unrecovered panic happens, unwindm will 492 // restore the g->sched.sp from the stack location 493 // and then systemstack will try to use it. If we don't set it here, 494 // that restored SP will be uninitialized (typically 0) and 495 // will not be usable. 496 MOVV g_m(g), R12 497 MOVV m_g0(R12), R19 498 MOVV R3, (g_sched+gobuf_sp)(R19) 499 500 havem: 501 // Now there's a valid m, and we're running on its m->g0. 502 // Save current m->g0->sched.sp on stack and then set it to SP. 503 // Save current sp in m->g0->sched.sp in preparation for 504 // switch back to m->curg stack. 505 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP). 506 MOVV m_g0(R12), R19 507 MOVV (g_sched+gobuf_sp)(R19), R13 508 MOVV R13, savedsp-24(SP) // must match frame size 509 MOVV R3, (g_sched+gobuf_sp)(R19) 510 511 // Switch to m->curg stack and call runtime.cgocallbackg. 512 // Because we are taking over the execution of m->curg 513 // but *not* resuming what had been running, we need to 514 // save that information (m->curg->sched) so we can restore it. 515 // We can restore m->curg->sched.sp easily, because calling 516 // runtime.cgocallbackg leaves SP unchanged upon return. 517 // To save m->curg->sched.pc, we push it onto the stack. 518 // This has the added benefit that it looks to the traceback 519 // routine like cgocallbackg is going to return to that 520 // PC (because the frame we allocate below has the same 521 // size as cgocallback_gofunc's frame declared above) 522 // so that the traceback will seamlessly trace back into 523 // the earlier calls. 524 MOVV m_curg(R12), g 525 JAL runtime·save_g(SB) 526 MOVV (g_sched+gobuf_sp)(g), R13 // prepare stack as R13 527 MOVV (g_sched+gobuf_pc)(g), R4 528 MOVV R4, -(24+8)(R13) // "saved LR"; must match frame size 529 MOVV fn+0(FP), R5 530 MOVV frame+8(FP), R6 531 MOVV ctxt+16(FP), R7 532 MOVV $-(24+8)(R13), R3 533 MOVV R5, 8(R3) 534 MOVV R6, 16(R3) 535 MOVV R7, 24(R3) 536 JAL runtime·cgocallbackg(SB) 537 538 // Restore g->sched (== m->curg->sched) from saved values. 539 MOVV 0(R3), R4 540 MOVV R4, (g_sched+gobuf_pc)(g) 541 MOVV $(24+8)(R3), R13 // must match frame size 542 MOVV R13, (g_sched+gobuf_sp)(g) 543 544 // Switch back to m->g0's stack and restore m->g0->sched.sp. 545 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 546 // so we do not have to restore it.) 547 MOVV g_m(g), R12 548 MOVV m_g0(R12), g 549 JAL runtime·save_g(SB) 550 MOVV (g_sched+gobuf_sp)(g), R3 551 MOVV savedsp-24(SP), R13 // must match frame size 552 MOVV R13, (g_sched+gobuf_sp)(g) 553 554 // If the m on entry was nil, we called needm above to borrow an m 555 // for the duration of the call. Since the call is over, return it with dropm. 556 MOVV savedm-8(SP), R12 557 BNE R12, droppedm 558 MOVV $runtime·dropm(SB), R4 559 JAL (R4) 560 droppedm: 561 562 // Done! 563 RET 564 565 // void setg(G*); set g. for use by needm. 566 TEXT runtime·setg(SB), NOSPLIT, $0-8 567 MOVV gg+0(FP), g 568 // This only happens if iscgo, so jump straight to save_g 569 JAL runtime·save_g(SB) 570 RET 571 572 // void setg_gcc(G*); set g called from gcc with g in R19 573 TEXT setg_gcc<>(SB),NOSPLIT,$0-0 574 MOVV R19, g 575 JAL runtime·save_g(SB) 576 RET 577 578 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 579 MOVW (R0), R0 580 UNDEF 581 582 // AES hashing not implemented for loong64 583 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 584 JMP runtime·memhashFallback(SB) 585 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 586 JMP runtime·strhashFallback(SB) 587 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 588 JMP runtime·memhash32Fallback(SB) 589 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 590 JMP runtime·memhash64Fallback(SB) 591 592 TEXT runtime·return0(SB), NOSPLIT, $0 593 MOVW $0, R19 594 RET 595 596 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 597 // Must obey the gcc calling convention. 598 TEXT _cgo_topofstack(SB),NOSPLIT,$16 599 // g (R22) and REGTMP (R30) might be clobbered by load_g. They 600 // are callee-save in the gcc calling convention, so save them. 601 MOVV R30, savedREGTMP-16(SP) 602 MOVV g, savedG-8(SP) 603 604 JAL runtime·load_g(SB) 605 MOVV g_m(g), R19 606 MOVV m_curg(R19), R19 607 MOVV (g_stack+stack_hi)(R19), R4 // return value in R4 608 609 MOVV savedG-8(SP), g 610 MOVV savedREGTMP-16(SP), R30 611 RET 612 613 // The top-most function running on a goroutine 614 // returns to goexit+PCQuantum. 615 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 616 NOOP 617 JAL runtime·goexit1(SB) // does not return 618 // traceback from goexit1 must hit code range of goexit 619 NOOP 620 621 TEXT ·checkASM(SB),NOSPLIT,$0-1 622 MOVW $1, R19 623 MOVB R19, ret+0(FP) 624 RET 625 626 // gcWriteBarrier informs the GC about heap pointer writes. 627 // 628 // gcWriteBarrier does NOT follow the Go ABI. It accepts the 629 // number of bytes of buffer needed in R29, and returns a pointer 630 // to the buffer space in R29. 631 // It clobbers R30 (the linker temp register). 632 // The act of CALLing gcWriteBarrier will clobber R1 (LR). 633 // It does not clobber any other general-purpose registers, 634 // but may clobber others (e.g., floating point registers). 635 TEXT gcWriteBarrier<>(SB),NOSPLIT,$216 636 // Save the registers clobbered by the fast path. 637 MOVV R19, 208(R3) 638 MOVV R13, 216(R3) 639 retry: 640 MOVV g_m(g), R19 641 MOVV m_p(R19), R19 642 MOVV (p_wbBuf+wbBuf_next)(R19), R13 643 MOVV (p_wbBuf+wbBuf_end)(R19), R30 // R30 is linker temp register 644 // Increment wbBuf.next position. 645 ADDV R29, R13 646 // Is the buffer full? 647 BLTU R30, R13, flush 648 // Commit to the larger buffer. 649 MOVV R13, (p_wbBuf+wbBuf_next)(R19) 650 // Make return value (the original next position) 651 SUBV R29, R13, R29 652 // Restore registers. 653 MOVV 208(R3), R19 654 MOVV 216(R3), R13 655 RET 656 657 flush: 658 // Save all general purpose registers since these could be 659 // clobbered by wbBufFlush and were not saved by the caller. 660 MOVV R27, 8(R3) 661 MOVV R28, 16(R3) 662 // R1 is LR, which was saved by the prologue. 663 MOVV R2, 24(R3) 664 // R3 is SP. 665 MOVV R4, 32(R3) 666 MOVV R5, 40(R3) 667 MOVV R6, 48(R3) 668 MOVV R7, 56(R3) 669 MOVV R8, 64(R3) 670 MOVV R9, 72(R3) 671 MOVV R10, 80(R3) 672 MOVV R11, 88(R3) 673 MOVV R12, 96(R3) 674 // R13 already saved 675 MOVV R14, 104(R3) 676 MOVV R15, 112(R3) 677 MOVV R16, 120(R3) 678 MOVV R17, 128(R3) 679 MOVV R18, 136(R3) 680 // R19 already saved 681 MOVV R20, 144(R3) 682 MOVV R21, 152(R3) 683 // R22 is g. 684 MOVV R23, 160(R3) 685 MOVV R24, 168(R3) 686 MOVV R25, 176(R3) 687 MOVV R26, 184(R3) 688 // R27 already saved 689 // R28 already saved. 690 MOVV R29, 192(R3) 691 // R30 is tmp register. 692 MOVV R31, 200(R3) 693 694 CALL runtime·wbBufFlush(SB) 695 696 MOVV 8(R3), R27 697 MOVV 16(R3), R28 698 MOVV 24(R3), R2 699 MOVV 32(R3), R4 700 MOVV 40(R3), R5 701 MOVV 48(R3), R6 702 MOVV 56(R3), R7 703 MOVV 64(R3), R8 704 MOVV 72(R3), R9 705 MOVV 80(R3), R10 706 MOVV 88(R3), R11 707 MOVV 96(R3), R12 708 MOVV 104(R3), R14 709 MOVV 112(R3), R15 710 MOVV 120(R3), R16 711 MOVV 128(R3), R17 712 MOVV 136(R3), R18 713 MOVV 144(R3), R20 714 MOVV 152(R3), R21 715 MOVV 160(R3), R23 716 MOVV 168(R3), R24 717 MOVV 176(R3), R25 718 MOVV 184(R3), R26 719 MOVV 192(R3), R29 720 MOVV 200(R3), R31 721 JMP retry 722 723 TEXT runtime·gcWriteBarrier1<ABIInternal>(SB),NOSPLIT,$0 724 MOVV $8, R29 725 JMP gcWriteBarrier<>(SB) 726 TEXT runtime·gcWriteBarrier2<ABIInternal>(SB),NOSPLIT,$0 727 MOVV $16, R29 728 JMP gcWriteBarrier<>(SB) 729 TEXT runtime·gcWriteBarrier3<ABIInternal>(SB),NOSPLIT,$0 730 MOVV $24, R29 731 JMP gcWriteBarrier<>(SB) 732 TEXT runtime·gcWriteBarrier4<ABIInternal>(SB),NOSPLIT,$0 733 MOVV $32, R29 734 JMP gcWriteBarrier<>(SB) 735 TEXT runtime·gcWriteBarrier5<ABIInternal>(SB),NOSPLIT,$0 736 MOVV $40, R29 737 JMP gcWriteBarrier<>(SB) 738 TEXT runtime·gcWriteBarrier6<ABIInternal>(SB),NOSPLIT,$0 739 MOVV $48, R29 740 JMP gcWriteBarrier<>(SB) 741 TEXT runtime·gcWriteBarrier7<ABIInternal>(SB),NOSPLIT,$0 742 MOVV $56, R29 743 JMP gcWriteBarrier<>(SB) 744 TEXT runtime·gcWriteBarrier8<ABIInternal>(SB),NOSPLIT,$0 745 MOVV $64, R29 746 JMP gcWriteBarrier<>(SB) 747 748 // Note: these functions use a special calling convention to save generated code space. 749 // Arguments are passed in registers, but the space for those arguments are allocated 750 // in the caller's stack frame. These stubs write the args into that stack space and 751 // then tail call to the corresponding runtime handler. 752 // The tail call makes these stubs disappear in backtraces. 753 TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 754 MOVV R19, x+0(FP) 755 MOVV R18, y+8(FP) 756 JMP runtime·goPanicIndex(SB) 757 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 758 MOVV R19, x+0(FP) 759 MOVV R18, y+8(FP) 760 JMP runtime·goPanicIndexU(SB) 761 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 762 MOVV R18, x+0(FP) 763 MOVV R17, y+8(FP) 764 JMP runtime·goPanicSliceAlen(SB) 765 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 766 MOVV R18, x+0(FP) 767 MOVV R17, y+8(FP) 768 JMP runtime·goPanicSliceAlenU(SB) 769 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 770 MOVV R18, x+0(FP) 771 MOVV R17, y+8(FP) 772 JMP runtime·goPanicSliceAcap(SB) 773 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 774 MOVV R18, x+0(FP) 775 MOVV R17, y+8(FP) 776 JMP runtime·goPanicSliceAcapU(SB) 777 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 778 MOVV R19, x+0(FP) 779 MOVV R18, y+8(FP) 780 JMP runtime·goPanicSliceB(SB) 781 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 782 MOVV R19, x+0(FP) 783 MOVV R18, y+8(FP) 784 JMP runtime·goPanicSliceBU(SB) 785 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 786 MOVV R17, x+0(FP) 787 MOVV R4, y+8(FP) 788 JMP runtime·goPanicSlice3Alen(SB) 789 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 790 MOVV R17, x+0(FP) 791 MOVV R4, y+8(FP) 792 JMP runtime·goPanicSlice3AlenU(SB) 793 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 794 MOVV R17, x+0(FP) 795 MOVV R4, y+8(FP) 796 JMP runtime·goPanicSlice3Acap(SB) 797 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 798 MOVV R17, x+0(FP) 799 MOVV R4, y+8(FP) 800 JMP runtime·goPanicSlice3AcapU(SB) 801 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 802 MOVV R18, x+0(FP) 803 MOVV R17, y+8(FP) 804 JMP runtime·goPanicSlice3B(SB) 805 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 806 MOVV R18, x+0(FP) 807 MOVV R17, y+8(FP) 808 JMP runtime·goPanicSlice3BU(SB) 809 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 810 MOVV R19, x+0(FP) 811 MOVV R18, y+8(FP) 812 JMP runtime·goPanicSlice3C(SB) 813 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 814 MOVV R19, x+0(FP) 815 MOVV R18, y+8(FP) 816 JMP runtime·goPanicSlice3CU(SB) 817 TEXT runtime·panicSliceConvert(SB),NOSPLIT,$0-16 818 MOVV R17, x+0(FP) 819 MOVV R4, y+8(FP) 820 JMP runtime·goPanicSliceConvert(SB)