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