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