github.com/mh-cbon/go@v0.0.0-20160603070303-9e112a3fe4c0/src/runtime/asm_mips64x.s (about) 1 // Copyright 2015 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 // +build mips64 mips64le 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,$0 15 // R29 = stack; R4 = argc; R5 = argv 16 17 // initialize essential registers 18 JAL runtime·reginit(SB) 19 20 ADDV $-24, R29 21 MOVW R4, 8(R29) // argc 22 MOVV R5, 16(R29) // argv 23 24 // create istack out of the given (operating system) stack. 25 // _cgo_init may update stackguard. 26 MOVV $runtime·g0(SB), g 27 MOVV $(-64*1024), R23 28 ADDV R23, R29, R1 29 MOVV R1, g_stackguard0(g) 30 MOVV R1, g_stackguard1(g) 31 MOVV R1, (g_stack+stack_lo)(g) 32 MOVV R29, (g_stack+stack_hi)(g) 33 34 // if there is a _cgo_init, call it using the gcc ABI. 35 MOVV _cgo_init(SB), R25 36 BEQ R25, nocgo 37 38 MOVV R0, R7 // arg 3: not used 39 MOVV R0, R6 // arg 2: not used 40 MOVV $setg_gcc<>(SB), R5 // arg 1: setg 41 MOVV g, R4 // arg 0: G 42 JAL (R25) 43 44 nocgo: 45 // update stackguard after _cgo_init 46 MOVV (g_stack+stack_lo)(g), R1 47 ADDV $const__StackGuard, R1 48 MOVV R1, g_stackguard0(g) 49 MOVV R1, g_stackguard1(g) 50 51 // set the per-goroutine and per-mach "registers" 52 MOVV $runtime·m0(SB), R1 53 54 // save m->g0 = g0 55 MOVV g, m_g0(R1) 56 // save m0 to g0->m 57 MOVV R1, g_m(g) 58 59 JAL runtime·check(SB) 60 61 // args are already prepared 62 JAL runtime·args(SB) 63 JAL runtime·osinit(SB) 64 JAL runtime·schedinit(SB) 65 66 // create a new goroutine to start program 67 MOVV $runtime·mainPC(SB), R1 // entry 68 ADDV $-24, R29 69 MOVV R1, 16(R29) 70 MOVV R0, 8(R29) 71 MOVV R0, 0(R29) 72 JAL runtime·newproc(SB) 73 ADDV $24, R29 74 75 // start this M 76 JAL runtime·mstart(SB) 77 78 MOVV R0, 1(R0) 79 RET 80 81 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 82 GLOBL runtime·mainPC(SB),RODATA,$8 83 84 TEXT runtime·breakpoint(SB),NOSPLIT,$-8-0 85 MOVV R0, 2(R0) // TODO: TD 86 RET 87 88 TEXT runtime·asminit(SB),NOSPLIT,$-8-0 89 RET 90 91 TEXT _cgo_reginit(SB),NOSPLIT,$-8-0 92 // crosscall1 needs to reginit, but can't 93 // get at the 'runtime.reginit' symbol. 94 JMP runtime·reginit(SB) 95 96 TEXT runtime·reginit(SB),NOSPLIT,$-8-0 97 // initialize essential FP registers 98 MOVD $0.5, F26 99 SUBD F26, F26, F24 100 ADDD F26, F26, F28 101 ADDD F28, F28, F30 102 RET 103 104 /* 105 * go-routine 106 */ 107 108 // void gosave(Gobuf*) 109 // save state in Gobuf; setjmp 110 TEXT runtime·gosave(SB), NOSPLIT, $-8-8 111 MOVV buf+0(FP), R1 112 MOVV R29, gobuf_sp(R1) 113 MOVV R31, gobuf_pc(R1) 114 MOVV g, gobuf_g(R1) 115 MOVV R0, gobuf_lr(R1) 116 MOVV R0, gobuf_ret(R1) 117 MOVV R0, gobuf_ctxt(R1) 118 RET 119 120 // void gogo(Gobuf*) 121 // restore state from Gobuf; longjmp 122 TEXT runtime·gogo(SB), NOSPLIT, $-8-8 123 MOVV buf+0(FP), R3 124 MOVV gobuf_g(R3), g // make sure g is not nil 125 JAL runtime·save_g(SB) 126 127 MOVV 0(g), R2 128 MOVV gobuf_sp(R3), R29 129 MOVV gobuf_lr(R3), R31 130 MOVV gobuf_ret(R3), R1 131 MOVV gobuf_ctxt(R3), REGCTXT 132 MOVV R0, gobuf_sp(R3) 133 MOVV R0, gobuf_ret(R3) 134 MOVV R0, gobuf_lr(R3) 135 MOVV R0, gobuf_ctxt(R3) 136 MOVV gobuf_pc(R3), R4 137 JMP (R4) 138 139 // void mcall(fn func(*g)) 140 // Switch to m->g0's stack, call fn(g). 141 // Fn must never return. It should gogo(&g->sched) 142 // to keep running g. 143 TEXT runtime·mcall(SB), NOSPLIT, $-8-8 144 // Save caller state in g->sched 145 MOVV R29, (g_sched+gobuf_sp)(g) 146 MOVV R31, (g_sched+gobuf_pc)(g) 147 MOVV R0, (g_sched+gobuf_lr)(g) 148 MOVV g, (g_sched+gobuf_g)(g) 149 150 // Switch to m->g0 & its stack, call fn. 151 MOVV g, R1 152 MOVV g_m(g), R3 153 MOVV m_g0(R3), g 154 JAL runtime·save_g(SB) 155 BNE g, R1, 2(PC) 156 JMP runtime·badmcall(SB) 157 MOVV fn+0(FP), REGCTXT // context 158 MOVV 0(REGCTXT), R4 // code pointer 159 MOVV (g_sched+gobuf_sp)(g), R29 // sp = m->g0->sched.sp 160 ADDV $-16, R29 161 MOVV R1, 8(R29) 162 MOVV R0, 0(R29) 163 JAL (R4) 164 JMP runtime·badmcall2(SB) 165 166 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 167 // of the G stack. We need to distinguish the routine that 168 // lives at the bottom of the G stack from the one that lives 169 // at the top of the system stack because the one at the top of 170 // the system stack terminates the stack walk (see topofstack()). 171 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 172 UNDEF 173 JAL (R31) // make sure this function is not leaf 174 RET 175 176 // func systemstack(fn func()) 177 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 178 MOVV fn+0(FP), R1 // R1 = fn 179 MOVV R1, REGCTXT // context 180 MOVV g_m(g), R2 // R2 = m 181 182 MOVV m_gsignal(R2), R3 // R3 = gsignal 183 BEQ g, R3, noswitch 184 185 MOVV m_g0(R2), R3 // R3 = g0 186 BEQ g, R3, noswitch 187 188 MOVV m_curg(R2), R4 189 BEQ g, R4, switch 190 191 // Bad: g is not gsignal, not g0, not curg. What is it? 192 // Hide call from linker nosplit analysis. 193 MOVV $runtime·badsystemstack(SB), R4 194 JAL (R4) 195 196 switch: 197 // save our state in g->sched. Pretend to 198 // be systemstack_switch if the G stack is scanned. 199 MOVV $runtime·systemstack_switch(SB), R4 200 ADDV $8, R4 // get past prologue 201 MOVV R4, (g_sched+gobuf_pc)(g) 202 MOVV R29, (g_sched+gobuf_sp)(g) 203 MOVV R0, (g_sched+gobuf_lr)(g) 204 MOVV g, (g_sched+gobuf_g)(g) 205 206 // switch to g0 207 MOVV R3, g 208 JAL runtime·save_g(SB) 209 MOVV (g_sched+gobuf_sp)(g), R1 210 // make it look like mstart called systemstack on g0, to stop traceback 211 ADDV $-8, R1 212 MOVV $runtime·mstart(SB), R2 213 MOVV R2, 0(R1) 214 MOVV R1, R29 215 216 // call target function 217 MOVV 0(REGCTXT), R4 // code pointer 218 JAL (R4) 219 220 // switch back to g 221 MOVV g_m(g), R1 222 MOVV m_curg(R1), g 223 JAL runtime·save_g(SB) 224 MOVV (g_sched+gobuf_sp)(g), R29 225 MOVV R0, (g_sched+gobuf_sp)(g) 226 RET 227 228 noswitch: 229 // already on m stack, just call directly 230 MOVV 0(REGCTXT), R4 // code pointer 231 JAL (R4) 232 RET 233 234 /* 235 * support for morestack 236 */ 237 238 // Called during function prolog when more stack is needed. 239 // Caller has already loaded: 240 // R1: framesize, R2: argsize, R3: LR 241 // 242 // The traceback routines see morestack on a g0 as being 243 // the top of a stack (for example, morestack calling newstack 244 // calling the scheduler calling newm calling gc), so we must 245 // record an argument size. For that purpose, it has no arguments. 246 TEXT runtime·morestack(SB),NOSPLIT,$-8-0 247 // Cannot grow scheduler stack (m->g0). 248 MOVV g_m(g), R7 249 MOVV m_g0(R7), R8 250 BNE g, R8, 2(PC) 251 JAL runtime·abort(SB) 252 253 // Cannot grow signal stack (m->gsignal). 254 MOVV m_gsignal(R7), R8 255 BNE g, R8, 2(PC) 256 JAL runtime·abort(SB) 257 258 // Called from f. 259 // Set g->sched to context in f. 260 MOVV REGCTXT, (g_sched+gobuf_ctxt)(g) 261 MOVV R29, (g_sched+gobuf_sp)(g) 262 MOVV R31, (g_sched+gobuf_pc)(g) 263 MOVV R3, (g_sched+gobuf_lr)(g) 264 265 // Called from f. 266 // Set m->morebuf to f's caller. 267 MOVV R3, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 268 MOVV R29, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 269 MOVV g, (m_morebuf+gobuf_g)(R7) 270 271 // Call newstack on m->g0's stack. 272 MOVV m_g0(R7), g 273 JAL runtime·save_g(SB) 274 MOVV (g_sched+gobuf_sp)(g), R29 275 JAL runtime·newstack(SB) 276 277 // Not reached, but make sure the return PC from the call to newstack 278 // is still in this function, and not the beginning of the next. 279 UNDEF 280 281 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$-8-0 282 MOVV R0, REGCTXT 283 JMP runtime·morestack(SB) 284 285 TEXT runtime·stackBarrier(SB),NOSPLIT,$0 286 // We came here via a RET to an overwritten LR. 287 // R1 may be live. Other registers are available. 288 289 // Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal. 290 MOVV (g_stkbar+slice_array)(g), R2 291 MOVV g_stkbarPos(g), R3 292 MOVV $stkbar__size, R4 293 MULVU R3, R4 294 MOVV LO, R4 295 ADDV R2, R4 296 MOVV stkbar_savedLRVal(R4), R4 297 // Record that this stack barrier was hit. 298 ADDV $1, R3 299 MOVV R3, g_stkbarPos(g) 300 // Jump to the original return PC. 301 JMP (R4) 302 303 // reflectcall: call a function with the given argument list 304 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 305 // we don't have variable-sized frames, so we use a small number 306 // of constant-sized-frame functions to encode a few bits of size in the pc. 307 // Caution: ugly multiline assembly macros in your future! 308 309 #define DISPATCH(NAME,MAXSIZE) \ 310 MOVV $MAXSIZE, R23; \ 311 SGTU R1, R23, R23; \ 312 BNE R23, 3(PC); \ 313 MOVV $NAME(SB), R4; \ 314 JMP (R4) 315 // Note: can't just "BR NAME(SB)" - bad inlining results. 316 317 TEXT reflect·call(SB), NOSPLIT, $0-0 318 JMP ·reflectcall(SB) 319 320 TEXT ·reflectcall(SB), NOSPLIT, $-8-32 321 MOVWU argsize+24(FP), R1 322 // NOTE(rsc): No call16, because CALLFN needs four words 323 // of argument space to invoke callwritebarrier. 324 DISPATCH(runtime·call32, 32) 325 DISPATCH(runtime·call64, 64) 326 DISPATCH(runtime·call128, 128) 327 DISPATCH(runtime·call256, 256) 328 DISPATCH(runtime·call512, 512) 329 DISPATCH(runtime·call1024, 1024) 330 DISPATCH(runtime·call2048, 2048) 331 DISPATCH(runtime·call4096, 4096) 332 DISPATCH(runtime·call8192, 8192) 333 DISPATCH(runtime·call16384, 16384) 334 DISPATCH(runtime·call32768, 32768) 335 DISPATCH(runtime·call65536, 65536) 336 DISPATCH(runtime·call131072, 131072) 337 DISPATCH(runtime·call262144, 262144) 338 DISPATCH(runtime·call524288, 524288) 339 DISPATCH(runtime·call1048576, 1048576) 340 DISPATCH(runtime·call2097152, 2097152) 341 DISPATCH(runtime·call4194304, 4194304) 342 DISPATCH(runtime·call8388608, 8388608) 343 DISPATCH(runtime·call16777216, 16777216) 344 DISPATCH(runtime·call33554432, 33554432) 345 DISPATCH(runtime·call67108864, 67108864) 346 DISPATCH(runtime·call134217728, 134217728) 347 DISPATCH(runtime·call268435456, 268435456) 348 DISPATCH(runtime·call536870912, 536870912) 349 DISPATCH(runtime·call1073741824, 1073741824) 350 MOVV $runtime·badreflectcall(SB), R4 351 JMP (R4) 352 353 #define CALLFN(NAME,MAXSIZE) \ 354 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 355 NO_LOCAL_POINTERS; \ 356 /* copy arguments to stack */ \ 357 MOVV arg+16(FP), R1; \ 358 MOVWU argsize+24(FP), R2; \ 359 MOVV R29, R3; \ 360 ADDV $8, R3; \ 361 ADDV R3, R2; \ 362 BEQ R3, R2, 6(PC); \ 363 MOVBU (R1), R4; \ 364 ADDV $1, R1; \ 365 MOVBU R4, (R3); \ 366 ADDV $1, R3; \ 367 JMP -5(PC); \ 368 /* call function */ \ 369 MOVV f+8(FP), REGCTXT; \ 370 MOVV (REGCTXT), R4; \ 371 PCDATA $PCDATA_StackMapIndex, $0; \ 372 JAL (R4); \ 373 /* copy return values back */ \ 374 MOVV arg+16(FP), R1; \ 375 MOVWU n+24(FP), R2; \ 376 MOVWU retoffset+28(FP), R4; \ 377 MOVV R29, R3; \ 378 ADDV R4, R3; \ 379 ADDV R4, R1; \ 380 SUBVU R4, R2; \ 381 ADDV $8, R3; \ 382 ADDV R3, R2; \ 383 loop: \ 384 BEQ R3, R2, end; \ 385 MOVBU (R3), R4; \ 386 ADDV $1, R3; \ 387 MOVBU R4, (R1); \ 388 ADDV $1, R1; \ 389 JMP loop; \ 390 end: \ 391 /* execute write barrier updates */ \ 392 MOVV argtype+0(FP), R5; \ 393 MOVV arg+16(FP), R1; \ 394 MOVWU n+24(FP), R2; \ 395 MOVWU retoffset+28(FP), R4; \ 396 MOVV R5, 8(R29); \ 397 MOVV R1, 16(R29); \ 398 MOVV R2, 24(R29); \ 399 MOVV R4, 32(R29); \ 400 JAL runtime·callwritebarrier(SB); \ 401 RET 402 403 CALLFN(·call16, 16) 404 CALLFN(·call32, 32) 405 CALLFN(·call64, 64) 406 CALLFN(·call128, 128) 407 CALLFN(·call256, 256) 408 CALLFN(·call512, 512) 409 CALLFN(·call1024, 1024) 410 CALLFN(·call2048, 2048) 411 CALLFN(·call4096, 4096) 412 CALLFN(·call8192, 8192) 413 CALLFN(·call16384, 16384) 414 CALLFN(·call32768, 32768) 415 CALLFN(·call65536, 65536) 416 CALLFN(·call131072, 131072) 417 CALLFN(·call262144, 262144) 418 CALLFN(·call524288, 524288) 419 CALLFN(·call1048576, 1048576) 420 CALLFN(·call2097152, 2097152) 421 CALLFN(·call4194304, 4194304) 422 CALLFN(·call8388608, 8388608) 423 CALLFN(·call16777216, 16777216) 424 CALLFN(·call33554432, 33554432) 425 CALLFN(·call67108864, 67108864) 426 CALLFN(·call134217728, 134217728) 427 CALLFN(·call268435456, 268435456) 428 CALLFN(·call536870912, 536870912) 429 CALLFN(·call1073741824, 1073741824) 430 431 TEXT runtime·procyield(SB),NOSPLIT,$0-0 432 RET 433 434 // void jmpdefer(fv, sp); 435 // called from deferreturn. 436 // 1. grab stored LR for caller 437 // 2. sub 8 bytes to get back to JAL deferreturn 438 // 3. JMP to fn 439 TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16 440 MOVV 0(R29), R31 441 ADDV $-8, R31 442 443 MOVV fv+0(FP), REGCTXT 444 MOVV argp+8(FP), R29 445 ADDV $-8, R29 446 NOR R0, R0 // prevent scheduling 447 MOVV 0(REGCTXT), R4 448 JMP (R4) 449 450 // Save state of caller into g->sched. Smashes R31. 451 TEXT gosave<>(SB),NOSPLIT,$-8 452 MOVV R31, (g_sched+gobuf_pc)(g) 453 MOVV R29, (g_sched+gobuf_sp)(g) 454 MOVV R0, (g_sched+gobuf_lr)(g) 455 MOVV R0, (g_sched+gobuf_ret)(g) 456 MOVV R0, (g_sched+gobuf_ctxt)(g) 457 RET 458 459 // func asmcgocall(fn, arg unsafe.Pointer) int32 460 // Call fn(arg) on the scheduler stack, 461 // aligned appropriately for the gcc ABI. 462 // See cgocall.go for more details. 463 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 464 MOVV fn+0(FP), R25 465 MOVV arg+8(FP), R4 466 467 MOVV R29, R3 // save original stack pointer 468 MOVV g, R2 469 470 // Figure out if we need to switch to m->g0 stack. 471 // We get called to create new OS threads too, and those 472 // come in on the m->g0 stack already. 473 MOVV g_m(g), R5 474 MOVV m_g0(R5), R6 475 BEQ R6, g, g0 476 477 JAL gosave<>(SB) 478 MOVV R6, g 479 JAL runtime·save_g(SB) 480 MOVV (g_sched+gobuf_sp)(g), R29 481 482 // Now on a scheduling stack (a pthread-created stack). 483 g0: 484 // Save room for two of our pointers. 485 ADDV $-16, R29 486 MOVV R2, 0(R29) // save old g on stack 487 MOVV (g_stack+stack_hi)(R2), R2 488 SUBVU R3, R2 489 MOVV R2, 8(R29) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 490 JAL (R25) 491 492 // Restore g, stack pointer. R2 is return value. 493 MOVV 0(R29), g 494 JAL runtime·save_g(SB) 495 MOVV (g_stack+stack_hi)(g), R5 496 MOVV 8(R29), R6 497 SUBVU R6, R5 498 MOVV R5, R29 499 500 MOVW R2, ret+16(FP) 501 RET 502 503 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 504 // Turn the fn into a Go func (by taking its address) and call 505 // cgocallback_gofunc. 506 TEXT runtime·cgocallback(SB),NOSPLIT,$32-32 507 MOVV $fn+0(FP), R1 508 MOVV R1, 8(R29) 509 MOVV frame+8(FP), R1 510 MOVV R1, 16(R29) 511 MOVV framesize+16(FP), R1 512 MOVV R1, 24(R29) 513 MOVV ctxt+24(FP), R1 514 MOVV R1, 32(R29) 515 MOVV $runtime·cgocallback_gofunc(SB), R1 516 JAL (R1) 517 RET 518 519 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 520 // See cgocall.go for more details. 521 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32 522 NO_LOCAL_POINTERS 523 524 // Load m and g from thread-local storage. 525 MOVB runtime·iscgo(SB), R1 526 BEQ R1, nocgo 527 JAL runtime·load_g(SB) 528 nocgo: 529 530 // If g is nil, Go did not create the current thread. 531 // Call needm to obtain one for temporary use. 532 // In this case, we're running on the thread stack, so there's 533 // lots of space, but the linker doesn't know. Hide the call from 534 // the linker analysis by using an indirect call. 535 BEQ g, needm 536 537 MOVV g_m(g), R3 538 MOVV R3, savedm-8(SP) 539 JMP havem 540 541 needm: 542 MOVV g, savedm-8(SP) // g is zero, so is m. 543 MOVV $runtime·needm(SB), R4 544 JAL (R4) 545 546 // Set m->sched.sp = SP, so that if a panic happens 547 // during the function we are about to execute, it will 548 // have a valid SP to run on the g0 stack. 549 // The next few lines (after the havem label) 550 // will save this SP onto the stack and then write 551 // the same SP back to m->sched.sp. That seems redundant, 552 // but if an unrecovered panic happens, unwindm will 553 // restore the g->sched.sp from the stack location 554 // and then systemstack will try to use it. If we don't set it here, 555 // that restored SP will be uninitialized (typically 0) and 556 // will not be usable. 557 MOVV g_m(g), R3 558 MOVV m_g0(R3), R1 559 MOVV R29, (g_sched+gobuf_sp)(R1) 560 561 havem: 562 // Now there's a valid m, and we're running on its m->g0. 563 // Save current m->g0->sched.sp on stack and then set it to SP. 564 // Save current sp in m->g0->sched.sp in preparation for 565 // switch back to m->curg stack. 566 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP). 567 MOVV m_g0(R3), R1 568 MOVV (g_sched+gobuf_sp)(R1), R2 569 MOVV R2, savedsp-16(SP) 570 MOVV R29, (g_sched+gobuf_sp)(R1) 571 572 // Switch to m->curg stack and call runtime.cgocallbackg. 573 // Because we are taking over the execution of m->curg 574 // but *not* resuming what had been running, we need to 575 // save that information (m->curg->sched) so we can restore it. 576 // We can restore m->curg->sched.sp easily, because calling 577 // runtime.cgocallbackg leaves SP unchanged upon return. 578 // To save m->curg->sched.pc, we push it onto the stack. 579 // This has the added benefit that it looks to the traceback 580 // routine like cgocallbackg is going to return to that 581 // PC (because the frame we allocate below has the same 582 // size as cgocallback_gofunc's frame declared above) 583 // so that the traceback will seamlessly trace back into 584 // the earlier calls. 585 // 586 // In the new goroutine, -8(SP) is unused (where SP refers to 587 // m->curg's SP while we're setting it up, before we've adjusted it). 588 MOVV m_curg(R3), g 589 JAL runtime·save_g(SB) 590 MOVV (g_sched+gobuf_sp)(g), R2 // prepare stack as R2 591 MOVV (g_sched+gobuf_pc)(g), R4 592 MOVV R4, -24(R2) 593 MOVV ctxt+24(FP), R1 594 MOVV R1, -16(R2) 595 MOVV $-24(R2), R29 596 JAL runtime·cgocallbackg(SB) 597 598 // Restore g->sched (== m->curg->sched) from saved values. 599 MOVV 0(R29), R4 600 MOVV R4, (g_sched+gobuf_pc)(g) 601 MOVV $24(R29), R2 602 MOVV R2, (g_sched+gobuf_sp)(g) 603 604 // Switch back to m->g0's stack and restore m->g0->sched.sp. 605 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 606 // so we do not have to restore it.) 607 MOVV g_m(g), R3 608 MOVV m_g0(R3), g 609 JAL runtime·save_g(SB) 610 MOVV (g_sched+gobuf_sp)(g), R29 611 MOVV savedsp-16(SP), R2 612 MOVV R2, (g_sched+gobuf_sp)(g) 613 614 // If the m on entry was nil, we called needm above to borrow an m 615 // for the duration of the call. Since the call is over, return it with dropm. 616 MOVV savedm-8(SP), R3 617 BNE R3, droppedm 618 MOVV $runtime·dropm(SB), R4 619 JAL (R4) 620 droppedm: 621 622 // Done! 623 RET 624 625 // void setg(G*); set g. for use by needm. 626 TEXT runtime·setg(SB), NOSPLIT, $0-8 627 MOVV gg+0(FP), g 628 // This only happens if iscgo, so jump straight to save_g 629 JAL runtime·save_g(SB) 630 RET 631 632 // void setg_gcc(G*); set g called from gcc with g in R1 633 TEXT setg_gcc<>(SB),NOSPLIT,$0-0 634 MOVV R1, g 635 JAL runtime·save_g(SB) 636 RET 637 638 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 639 MOVV 16(R29), R1 // LR saved by caller 640 MOVV runtime·stackBarrierPC(SB), R2 641 BNE R1, R2, nobar 642 // Get original return PC. 643 JAL runtime·nextBarrierPC(SB) 644 MOVV 8(R29), R1 645 nobar: 646 MOVV R1, ret+8(FP) 647 RET 648 649 TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16 650 MOVV pc+8(FP), R1 651 MOVV 16(R29), R2 652 MOVV runtime·stackBarrierPC(SB), R3 653 BEQ R2, R3, setbar 654 MOVV R1, 16(R29) // set LR in caller 655 RET 656 setbar: 657 // Set the stack barrier return PC. 658 MOVV R1, 8(R29) 659 JAL runtime·setNextBarrierPC(SB) 660 RET 661 662 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 663 MOVV argp+0(FP), R1 664 ADDV $-8, R1 665 MOVV R1, ret+8(FP) 666 RET 667 668 TEXT runtime·abort(SB),NOSPLIT,$-8-0 669 MOVW (R0), R0 670 UNDEF 671 672 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 673 // redirects to memhash(p, h, size) using the size 674 // stored in the closure. 675 TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24 676 GO_ARGS 677 NO_LOCAL_POINTERS 678 MOVV p+0(FP), R1 679 MOVV h+8(FP), R2 680 MOVV 8(REGCTXT), R3 681 MOVV R1, 8(R29) 682 MOVV R2, 16(R29) 683 MOVV R3, 24(R29) 684 JAL runtime·memhash(SB) 685 MOVV 32(R29), R1 686 MOVV R1, ret+16(FP) 687 RET 688 689 // AES hashing not implemented for mips64 690 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0 691 MOVW (R0), R1 692 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0 693 MOVW (R0), R1 694 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0 695 MOVW (R0), R1 696 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 697 MOVW (R0), R1 698 699 // memequal(p, q unsafe.Pointer, size uintptr) bool 700 TEXT runtime·memequal(SB),NOSPLIT,$-8-25 701 MOVV a+0(FP), R1 702 MOVV b+8(FP), R2 703 BEQ R1, R2, eq 704 MOVV size+16(FP), R3 705 ADDV R1, R3, R4 706 loop: 707 BNE R1, R4, test 708 MOVV $1, R1 709 MOVB R1, ret+24(FP) 710 RET 711 test: 712 MOVBU (R1), R6 713 ADDV $1, R1 714 MOVBU (R2), R7 715 ADDV $1, R2 716 BEQ R6, R7, loop 717 718 MOVB R0, ret+24(FP) 719 RET 720 eq: 721 MOVV $1, R1 722 MOVB R1, ret+24(FP) 723 RET 724 725 // memequal_varlen(a, b unsafe.Pointer) bool 726 TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 727 MOVV a+0(FP), R1 728 MOVV b+8(FP), R2 729 BEQ R1, R2, eq 730 MOVV 8(REGCTXT), R3 // compiler stores size at offset 8 in the closure 731 MOVV R1, 8(R29) 732 MOVV R2, 16(R29) 733 MOVV R3, 24(R29) 734 JAL runtime·memequal(SB) 735 MOVBU 32(R29), R1 736 MOVB R1, ret+16(FP) 737 RET 738 eq: 739 MOVV $1, R1 740 MOVB R1, ret+16(FP) 741 RET 742 743 // eqstring tests whether two strings are equal. 744 // The compiler guarantees that strings passed 745 // to eqstring have equal length. 746 // See runtime_test.go:eqstring_generic for 747 // equivalent Go code. 748 TEXT runtime·eqstring(SB),NOSPLIT,$0-33 749 MOVV s1str+0(FP), R1 750 MOVV s2str+16(FP), R2 751 MOVV $1, R3 752 MOVB R3, ret+32(FP) 753 BNE R1, R2, 2(PC) 754 RET 755 MOVV s1len+8(FP), R3 756 ADDV R1, R3, R4 757 loop: 758 BNE R1, R4, 2(PC) 759 RET 760 MOVBU (R1), R6 761 ADDV $1, R1 762 MOVBU (R2), R7 763 ADDV $1, R2 764 BEQ R6, R7, loop 765 MOVB R0, ret+32(FP) 766 RET 767 768 // TODO: share code with memequal? 769 TEXT bytes·Equal(SB),NOSPLIT,$0-49 770 MOVV a_len+8(FP), R3 771 MOVV b_len+32(FP), R4 772 BNE R3, R4, noteq // unequal lengths are not equal 773 774 MOVV a+0(FP), R1 775 MOVV b+24(FP), R2 776 ADDV R1, R3 // end 777 778 loop: 779 BEQ R1, R3, equal // reached the end 780 MOVBU (R1), R6 781 ADDV $1, R1 782 MOVBU (R2), R7 783 ADDV $1, R2 784 BEQ R6, R7, loop 785 786 noteq: 787 MOVB R0, ret+48(FP) 788 RET 789 790 equal: 791 MOVV $1, R1 792 MOVB R1, ret+48(FP) 793 RET 794 795 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 796 MOVV s+0(FP), R1 797 MOVV s_len+8(FP), R2 798 MOVBU c+24(FP), R3 // byte to find 799 MOVV R1, R4 // store base for later 800 ADDV R1, R2 // end 801 ADDV $-1, R1 802 803 loop: 804 ADDV $1, R1 805 BEQ R1, R2, notfound 806 MOVBU (R1), R5 807 BNE R3, R5, loop 808 809 SUBV R4, R1 // remove base 810 MOVV R1, ret+32(FP) 811 RET 812 813 notfound: 814 MOVV $-1, R1 815 MOVV R1, ret+32(FP) 816 RET 817 818 TEXT strings·IndexByte(SB),NOSPLIT,$0-32 819 MOVV p+0(FP), R1 820 MOVV b_len+8(FP), R2 821 MOVBU c+16(FP), R3 // byte to find 822 MOVV R1, R4 // store base for later 823 ADDV R1, R2 // end 824 ADDV $-1, R1 825 826 loop: 827 ADDV $1, R1 828 BEQ R1, R2, notfound 829 MOVBU (R1), R5 830 BNE R3, R5, loop 831 832 SUBV R4, R1 // remove base 833 MOVV R1, ret+24(FP) 834 RET 835 836 notfound: 837 MOVV $-1, R1 838 MOVV R1, ret+24(FP) 839 RET 840 841 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 842 MOVV g_m(g), R2 843 MOVWU m_fastrand(R2), R1 844 ADDU R1, R1 845 BGEZ R1, 2(PC) 846 XOR $0x88888eef, R1 847 MOVW R1, m_fastrand(R2) 848 MOVW R1, ret+0(FP) 849 RET 850 851 TEXT runtime·return0(SB), NOSPLIT, $0 852 MOVW $0, R1 853 RET 854 855 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 856 // Must obey the gcc calling convention. 857 TEXT _cgo_topofstack(SB),NOSPLIT,$16 858 // g (R30) and REGTMP (R23) might be clobbered by load_g. They 859 // are callee-save in the gcc calling convention, so save them. 860 MOVV R23, savedR23-16(SP) 861 MOVV g, savedG-8(SP) 862 863 JAL runtime·load_g(SB) 864 MOVV g_m(g), R1 865 MOVV m_curg(R1), R1 866 MOVV (g_stack+stack_hi)(R1), R2 // return value in R2 867 868 MOVV savedG-8(SP), g 869 MOVV savedR23-16(SP), R23 870 RET 871 872 // The top-most function running on a goroutine 873 // returns to goexit+PCQuantum. 874 TEXT runtime·goexit(SB),NOSPLIT,$-8-0 875 NOR R0, R0 // NOP 876 JAL runtime·goexit1(SB) // does not return 877 // traceback from goexit1 must hit code range of goexit 878 NOR R0, R0 // NOP 879 880 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 881 RET 882 883 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8 884 RET 885 886 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8 887 RET 888 889 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8 890 RET 891 892 TEXT ·checkASM(SB),NOSPLIT,$0-1 893 MOVW $1, R1 894 MOVB R1, ret+0(FP) 895 RET