github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/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 // reflectcall: call a function with the given argument list 290 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 291 // we don't have variable-sized frames, so we use a small number 292 // of constant-sized-frame functions to encode a few bits of size in the pc. 293 // Caution: ugly multiline assembly macros in your future! 294 295 #define DISPATCH(NAME,MAXSIZE) \ 296 MOVV $MAXSIZE, R23; \ 297 SGTU R1, R23, R23; \ 298 BNE R23, 3(PC); \ 299 MOVV $NAME(SB), R4; \ 300 JMP (R4) 301 // Note: can't just "BR NAME(SB)" - bad inlining results. 302 303 TEXT reflect·call(SB), NOSPLIT, $0-0 304 JMP ·reflectcall(SB) 305 306 TEXT ·reflectcall(SB), NOSPLIT, $-8-32 307 MOVWU argsize+24(FP), R1 308 DISPATCH(runtime·call32, 32) 309 DISPATCH(runtime·call64, 64) 310 DISPATCH(runtime·call128, 128) 311 DISPATCH(runtime·call256, 256) 312 DISPATCH(runtime·call512, 512) 313 DISPATCH(runtime·call1024, 1024) 314 DISPATCH(runtime·call2048, 2048) 315 DISPATCH(runtime·call4096, 4096) 316 DISPATCH(runtime·call8192, 8192) 317 DISPATCH(runtime·call16384, 16384) 318 DISPATCH(runtime·call32768, 32768) 319 DISPATCH(runtime·call65536, 65536) 320 DISPATCH(runtime·call131072, 131072) 321 DISPATCH(runtime·call262144, 262144) 322 DISPATCH(runtime·call524288, 524288) 323 DISPATCH(runtime·call1048576, 1048576) 324 DISPATCH(runtime·call2097152, 2097152) 325 DISPATCH(runtime·call4194304, 4194304) 326 DISPATCH(runtime·call8388608, 8388608) 327 DISPATCH(runtime·call16777216, 16777216) 328 DISPATCH(runtime·call33554432, 33554432) 329 DISPATCH(runtime·call67108864, 67108864) 330 DISPATCH(runtime·call134217728, 134217728) 331 DISPATCH(runtime·call268435456, 268435456) 332 DISPATCH(runtime·call536870912, 536870912) 333 DISPATCH(runtime·call1073741824, 1073741824) 334 MOVV $runtime·badreflectcall(SB), R4 335 JMP (R4) 336 337 #define CALLFN(NAME,MAXSIZE) \ 338 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 339 NO_LOCAL_POINTERS; \ 340 /* copy arguments to stack */ \ 341 MOVV arg+16(FP), R1; \ 342 MOVWU argsize+24(FP), R2; \ 343 MOVV R29, R3; \ 344 ADDV $8, R3; \ 345 ADDV R3, R2; \ 346 BEQ R3, R2, 6(PC); \ 347 MOVBU (R1), R4; \ 348 ADDV $1, R1; \ 349 MOVBU R4, (R3); \ 350 ADDV $1, R3; \ 351 JMP -5(PC); \ 352 /* call function */ \ 353 MOVV f+8(FP), REGCTXT; \ 354 MOVV (REGCTXT), R4; \ 355 PCDATA $PCDATA_StackMapIndex, $0; \ 356 JAL (R4); \ 357 /* copy return values back */ \ 358 MOVV argtype+0(FP), R5; \ 359 MOVV arg+16(FP), R1; \ 360 MOVWU n+24(FP), R2; \ 361 MOVWU retoffset+28(FP), R4; \ 362 ADDV $8, R29, R3; \ 363 ADDV R4, R3; \ 364 ADDV R4, R1; \ 365 SUBVU R4, R2; \ 366 JAL callRet<>(SB); \ 367 RET 368 369 // callRet copies return values back at the end of call*. This is a 370 // separate function so it can allocate stack space for the arguments 371 // to reflectcallmove. It does not follow the Go ABI; it expects its 372 // arguments in registers. 373 TEXT callRet<>(SB), NOSPLIT, $32-0 374 MOVV R5, 8(R29) 375 MOVV R1, 16(R29) 376 MOVV R3, 24(R29) 377 MOVV R2, 32(R29) 378 JAL runtime·reflectcallmove(SB) 379 RET 380 381 CALLFN(·call16, 16) 382 CALLFN(·call32, 32) 383 CALLFN(·call64, 64) 384 CALLFN(·call128, 128) 385 CALLFN(·call256, 256) 386 CALLFN(·call512, 512) 387 CALLFN(·call1024, 1024) 388 CALLFN(·call2048, 2048) 389 CALLFN(·call4096, 4096) 390 CALLFN(·call8192, 8192) 391 CALLFN(·call16384, 16384) 392 CALLFN(·call32768, 32768) 393 CALLFN(·call65536, 65536) 394 CALLFN(·call131072, 131072) 395 CALLFN(·call262144, 262144) 396 CALLFN(·call524288, 524288) 397 CALLFN(·call1048576, 1048576) 398 CALLFN(·call2097152, 2097152) 399 CALLFN(·call4194304, 4194304) 400 CALLFN(·call8388608, 8388608) 401 CALLFN(·call16777216, 16777216) 402 CALLFN(·call33554432, 33554432) 403 CALLFN(·call67108864, 67108864) 404 CALLFN(·call134217728, 134217728) 405 CALLFN(·call268435456, 268435456) 406 CALLFN(·call536870912, 536870912) 407 CALLFN(·call1073741824, 1073741824) 408 409 TEXT runtime·procyield(SB),NOSPLIT,$0-0 410 RET 411 412 // void jmpdefer(fv, sp); 413 // called from deferreturn. 414 // 1. grab stored LR for caller 415 // 2. sub 8 bytes to get back to JAL deferreturn 416 // 3. JMP to fn 417 TEXT runtime·jmpdefer(SB), NOSPLIT, $-8-16 418 MOVV 0(R29), R31 419 ADDV $-8, R31 420 421 MOVV fv+0(FP), REGCTXT 422 MOVV argp+8(FP), R29 423 ADDV $-8, R29 424 NOR R0, R0 // prevent scheduling 425 MOVV 0(REGCTXT), R4 426 JMP (R4) 427 428 // Save state of caller into g->sched. Smashes R1. 429 TEXT gosave<>(SB),NOSPLIT,$-8 430 MOVV R31, (g_sched+gobuf_pc)(g) 431 MOVV R29, (g_sched+gobuf_sp)(g) 432 MOVV R0, (g_sched+gobuf_lr)(g) 433 MOVV R0, (g_sched+gobuf_ret)(g) 434 // Assert ctxt is zero. See func save. 435 MOVV (g_sched+gobuf_ctxt)(g), R1 436 BEQ R1, 2(PC) 437 JAL runtime·badctxt(SB) 438 RET 439 440 // func asmcgocall(fn, arg unsafe.Pointer) int32 441 // Call fn(arg) on the scheduler stack, 442 // aligned appropriately for the gcc ABI. 443 // See cgocall.go for more details. 444 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 445 MOVV fn+0(FP), R25 446 MOVV arg+8(FP), R4 447 448 MOVV R29, R3 // save original stack pointer 449 MOVV g, R2 450 451 // Figure out if we need to switch to m->g0 stack. 452 // We get called to create new OS threads too, and those 453 // come in on the m->g0 stack already. 454 MOVV g_m(g), R5 455 MOVV m_g0(R5), R6 456 BEQ R6, g, g0 457 458 JAL gosave<>(SB) 459 MOVV R6, g 460 JAL runtime·save_g(SB) 461 MOVV (g_sched+gobuf_sp)(g), R29 462 463 // Now on a scheduling stack (a pthread-created stack). 464 g0: 465 // Save room for two of our pointers. 466 ADDV $-16, R29 467 MOVV R2, 0(R29) // save old g on stack 468 MOVV (g_stack+stack_hi)(R2), R2 469 SUBVU R3, R2 470 MOVV R2, 8(R29) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 471 JAL (R25) 472 473 // Restore g, stack pointer. R2 is return value. 474 MOVV 0(R29), g 475 JAL runtime·save_g(SB) 476 MOVV (g_stack+stack_hi)(g), R5 477 MOVV 8(R29), R6 478 SUBVU R6, R5 479 MOVV R5, R29 480 481 MOVW R2, ret+16(FP) 482 RET 483 484 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 485 // Turn the fn into a Go func (by taking its address) and call 486 // cgocallback_gofunc. 487 TEXT runtime·cgocallback(SB),NOSPLIT,$32-32 488 MOVV $fn+0(FP), R1 489 MOVV R1, 8(R29) 490 MOVV frame+8(FP), R1 491 MOVV R1, 16(R29) 492 MOVV framesize+16(FP), R1 493 MOVV R1, 24(R29) 494 MOVV ctxt+24(FP), R1 495 MOVV R1, 32(R29) 496 MOVV $runtime·cgocallback_gofunc(SB), R1 497 JAL (R1) 498 RET 499 500 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 501 // See cgocall.go for more details. 502 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32 503 NO_LOCAL_POINTERS 504 505 // Load m and g from thread-local storage. 506 MOVB runtime·iscgo(SB), R1 507 BEQ R1, nocgo 508 JAL runtime·load_g(SB) 509 nocgo: 510 511 // If g is nil, Go did not create the current thread. 512 // Call needm to obtain one for temporary use. 513 // In this case, we're running on the thread stack, so there's 514 // lots of space, but the linker doesn't know. Hide the call from 515 // the linker analysis by using an indirect call. 516 BEQ g, needm 517 518 MOVV g_m(g), R3 519 MOVV R3, savedm-8(SP) 520 JMP havem 521 522 needm: 523 MOVV g, savedm-8(SP) // g is zero, so is m. 524 MOVV $runtime·needm(SB), R4 525 JAL (R4) 526 527 // Set m->sched.sp = SP, so that if a panic happens 528 // during the function we are about to execute, it will 529 // have a valid SP to run on the g0 stack. 530 // The next few lines (after the havem label) 531 // will save this SP onto the stack and then write 532 // the same SP back to m->sched.sp. That seems redundant, 533 // but if an unrecovered panic happens, unwindm will 534 // restore the g->sched.sp from the stack location 535 // and then systemstack will try to use it. If we don't set it here, 536 // that restored SP will be uninitialized (typically 0) and 537 // will not be usable. 538 MOVV g_m(g), R3 539 MOVV m_g0(R3), R1 540 MOVV R29, (g_sched+gobuf_sp)(R1) 541 542 havem: 543 // Now there's a valid m, and we're running on its m->g0. 544 // Save current m->g0->sched.sp on stack and then set it to SP. 545 // Save current sp in m->g0->sched.sp in preparation for 546 // switch back to m->curg stack. 547 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R29) aka savedsp-16(SP). 548 MOVV m_g0(R3), R1 549 MOVV (g_sched+gobuf_sp)(R1), R2 550 MOVV R2, savedsp-16(SP) 551 MOVV R29, (g_sched+gobuf_sp)(R1) 552 553 // Switch to m->curg stack and call runtime.cgocallbackg. 554 // Because we are taking over the execution of m->curg 555 // but *not* resuming what had been running, we need to 556 // save that information (m->curg->sched) so we can restore it. 557 // We can restore m->curg->sched.sp easily, because calling 558 // runtime.cgocallbackg leaves SP unchanged upon return. 559 // To save m->curg->sched.pc, we push it onto the stack. 560 // This has the added benefit that it looks to the traceback 561 // routine like cgocallbackg is going to return to that 562 // PC (because the frame we allocate below has the same 563 // size as cgocallback_gofunc's frame declared above) 564 // so that the traceback will seamlessly trace back into 565 // the earlier calls. 566 // 567 // In the new goroutine, -8(SP) is unused (where SP refers to 568 // m->curg's SP while we're setting it up, before we've adjusted it). 569 MOVV m_curg(R3), g 570 JAL runtime·save_g(SB) 571 MOVV (g_sched+gobuf_sp)(g), R2 // prepare stack as R2 572 MOVV (g_sched+gobuf_pc)(g), R4 573 MOVV R4, -24(R2) 574 MOVV ctxt+24(FP), R1 575 MOVV R1, -16(R2) 576 MOVV $-24(R2), R29 577 JAL runtime·cgocallbackg(SB) 578 579 // Restore g->sched (== m->curg->sched) from saved values. 580 MOVV 0(R29), R4 581 MOVV R4, (g_sched+gobuf_pc)(g) 582 MOVV $24(R29), R2 583 MOVV R2, (g_sched+gobuf_sp)(g) 584 585 // Switch back to m->g0's stack and restore m->g0->sched.sp. 586 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 587 // so we do not have to restore it.) 588 MOVV g_m(g), R3 589 MOVV m_g0(R3), g 590 JAL runtime·save_g(SB) 591 MOVV (g_sched+gobuf_sp)(g), R29 592 MOVV savedsp-16(SP), R2 593 MOVV R2, (g_sched+gobuf_sp)(g) 594 595 // If the m on entry was nil, we called needm above to borrow an m 596 // for the duration of the call. Since the call is over, return it with dropm. 597 MOVV savedm-8(SP), R3 598 BNE R3, droppedm 599 MOVV $runtime·dropm(SB), R4 600 JAL (R4) 601 droppedm: 602 603 // Done! 604 RET 605 606 // void setg(G*); set g. for use by needm. 607 TEXT runtime·setg(SB), NOSPLIT, $0-8 608 MOVV gg+0(FP), g 609 // This only happens if iscgo, so jump straight to save_g 610 JAL runtime·save_g(SB) 611 RET 612 613 // void setg_gcc(G*); set g called from gcc with g in R1 614 TEXT setg_gcc<>(SB),NOSPLIT,$0-0 615 MOVV R1, g 616 JAL runtime·save_g(SB) 617 RET 618 619 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 620 MOVV 16(R29), R1 // LR saved by caller 621 MOVV R1, ret+8(FP) 622 RET 623 624 TEXT runtime·abort(SB),NOSPLIT,$-8-0 625 MOVW (R0), R0 626 UNDEF 627 628 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 629 // redirects to memhash(p, h, size) using the size 630 // stored in the closure. 631 TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24 632 GO_ARGS 633 NO_LOCAL_POINTERS 634 MOVV p+0(FP), R1 635 MOVV h+8(FP), R2 636 MOVV 8(REGCTXT), R3 637 MOVV R1, 8(R29) 638 MOVV R2, 16(R29) 639 MOVV R3, 24(R29) 640 JAL runtime·memhash(SB) 641 MOVV 32(R29), R1 642 MOVV R1, ret+16(FP) 643 RET 644 645 // AES hashing not implemented for mips64 646 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0 647 MOVW (R0), R1 648 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0 649 MOVW (R0), R1 650 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0 651 MOVW (R0), R1 652 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 653 MOVW (R0), R1 654 655 // memequal(p, q unsafe.Pointer, size uintptr) bool 656 TEXT runtime·memequal(SB),NOSPLIT,$-8-25 657 MOVV a+0(FP), R1 658 MOVV b+8(FP), R2 659 BEQ R1, R2, eq 660 MOVV size+16(FP), R3 661 ADDV R1, R3, R4 662 loop: 663 BNE R1, R4, test 664 MOVV $1, R1 665 MOVB R1, ret+24(FP) 666 RET 667 test: 668 MOVBU (R1), R6 669 ADDV $1, R1 670 MOVBU (R2), R7 671 ADDV $1, R2 672 BEQ R6, R7, loop 673 674 MOVB R0, ret+24(FP) 675 RET 676 eq: 677 MOVV $1, R1 678 MOVB R1, ret+24(FP) 679 RET 680 681 // memequal_varlen(a, b unsafe.Pointer) bool 682 TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 683 MOVV a+0(FP), R1 684 MOVV b+8(FP), R2 685 BEQ R1, R2, eq 686 MOVV 8(REGCTXT), R3 // compiler stores size at offset 8 in the closure 687 MOVV R1, 8(R29) 688 MOVV R2, 16(R29) 689 MOVV R3, 24(R29) 690 JAL runtime·memequal(SB) 691 MOVBU 32(R29), R1 692 MOVB R1, ret+16(FP) 693 RET 694 eq: 695 MOVV $1, R1 696 MOVB R1, ret+16(FP) 697 RET 698 699 // eqstring tests whether two strings are equal. 700 // The compiler guarantees that strings passed 701 // to eqstring have equal length. 702 // See runtime_test.go:eqstring_generic for 703 // equivalent Go code. 704 TEXT runtime·eqstring(SB),NOSPLIT,$0-33 705 MOVV s1_base+0(FP), R1 706 MOVV s2_base+16(FP), R2 707 MOVV $1, R3 708 MOVB R3, ret+32(FP) 709 BNE R1, R2, 2(PC) 710 RET 711 MOVV s1_len+8(FP), R3 712 ADDV R1, R3, R4 713 loop: 714 BNE R1, R4, 2(PC) 715 RET 716 MOVBU (R1), R6 717 ADDV $1, R1 718 MOVBU (R2), R7 719 ADDV $1, R2 720 BEQ R6, R7, loop 721 MOVB R0, ret+32(FP) 722 RET 723 724 // TODO: share code with memequal? 725 TEXT bytes·Equal(SB),NOSPLIT,$0-49 726 MOVV a_len+8(FP), R3 727 MOVV b_len+32(FP), R4 728 BNE R3, R4, noteq // unequal lengths are not equal 729 730 MOVV a+0(FP), R1 731 MOVV b+24(FP), R2 732 ADDV R1, R3 // end 733 734 loop: 735 BEQ R1, R3, equal // reached the end 736 MOVBU (R1), R6 737 ADDV $1, R1 738 MOVBU (R2), R7 739 ADDV $1, R2 740 BEQ R6, R7, loop 741 742 noteq: 743 MOVB R0, ret+48(FP) 744 RET 745 746 equal: 747 MOVV $1, R1 748 MOVB R1, ret+48(FP) 749 RET 750 751 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 752 MOVV s+0(FP), R1 753 MOVV s_len+8(FP), R2 754 MOVBU c+24(FP), R3 // byte to find 755 MOVV R1, R4 // store base for later 756 ADDV R1, R2 // end 757 ADDV $-1, R1 758 759 loop: 760 ADDV $1, R1 761 BEQ R1, R2, notfound 762 MOVBU (R1), R5 763 BNE R3, R5, loop 764 765 SUBV R4, R1 // remove base 766 MOVV R1, ret+32(FP) 767 RET 768 769 notfound: 770 MOVV $-1, R1 771 MOVV R1, ret+32(FP) 772 RET 773 774 TEXT strings·IndexByte(SB),NOSPLIT,$0-32 775 MOVV p+0(FP), R1 776 MOVV b_len+8(FP), R2 777 MOVBU c+16(FP), R3 // byte to find 778 MOVV R1, R4 // store base for later 779 ADDV R1, R2 // end 780 ADDV $-1, R1 781 782 loop: 783 ADDV $1, R1 784 BEQ R1, R2, notfound 785 MOVBU (R1), R5 786 BNE R3, R5, loop 787 788 SUBV R4, R1 // remove base 789 MOVV R1, ret+24(FP) 790 RET 791 792 notfound: 793 MOVV $-1, R1 794 MOVV R1, ret+24(FP) 795 RET 796 797 TEXT runtime·return0(SB), NOSPLIT, $0 798 MOVW $0, R1 799 RET 800 801 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 802 // Must obey the gcc calling convention. 803 TEXT _cgo_topofstack(SB),NOSPLIT,$16 804 // g (R30) and REGTMP (R23) might be clobbered by load_g. They 805 // are callee-save in the gcc calling convention, so save them. 806 MOVV R23, savedR23-16(SP) 807 MOVV g, savedG-8(SP) 808 809 JAL runtime·load_g(SB) 810 MOVV g_m(g), R1 811 MOVV m_curg(R1), R1 812 MOVV (g_stack+stack_hi)(R1), R2 // return value in R2 813 814 MOVV savedG-8(SP), g 815 MOVV savedR23-16(SP), R23 816 RET 817 818 // The top-most function running on a goroutine 819 // returns to goexit+PCQuantum. 820 TEXT runtime·goexit(SB),NOSPLIT,$-8-0 821 NOR R0, R0 // NOP 822 JAL runtime·goexit1(SB) // does not return 823 // traceback from goexit1 must hit code range of goexit 824 NOR R0, R0 // NOP 825 826 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 827 RET 828 829 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8 830 RET 831 832 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8 833 RET 834 835 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8 836 RET 837 838 TEXT ·checkASM(SB),NOSPLIT,$0-1 839 MOVW $1, R1 840 MOVB R1, ret+0(FP) 841 RET