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