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