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