github.com/karrick/go@v0.0.0-20170817181416-d5b0ec858b37/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 // AES hashing not implemented for mips64 629 TEXT runtime·aeshash(SB),NOSPLIT,$-8-0 630 MOVW (R0), R1 631 TEXT runtime·aeshash32(SB),NOSPLIT,$-8-0 632 MOVW (R0), R1 633 TEXT runtime·aeshash64(SB),NOSPLIT,$-8-0 634 MOVW (R0), R1 635 TEXT runtime·aeshashstr(SB),NOSPLIT,$-8-0 636 MOVW (R0), R1 637 638 // memequal(p, q unsafe.Pointer, size uintptr) bool 639 TEXT runtime·memequal(SB),NOSPLIT,$-8-25 640 MOVV a+0(FP), R1 641 MOVV b+8(FP), R2 642 BEQ R1, R2, eq 643 MOVV size+16(FP), R3 644 ADDV R1, R3, R4 645 loop: 646 BNE R1, R4, test 647 MOVV $1, R1 648 MOVB R1, ret+24(FP) 649 RET 650 test: 651 MOVBU (R1), R6 652 ADDV $1, R1 653 MOVBU (R2), R7 654 ADDV $1, R2 655 BEQ R6, R7, loop 656 657 MOVB R0, ret+24(FP) 658 RET 659 eq: 660 MOVV $1, R1 661 MOVB R1, ret+24(FP) 662 RET 663 664 // memequal_varlen(a, b unsafe.Pointer) bool 665 TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 666 MOVV a+0(FP), R1 667 MOVV b+8(FP), R2 668 BEQ R1, R2, eq 669 MOVV 8(REGCTXT), R3 // compiler stores size at offset 8 in the closure 670 MOVV R1, 8(R29) 671 MOVV R2, 16(R29) 672 MOVV R3, 24(R29) 673 JAL runtime·memequal(SB) 674 MOVBU 32(R29), R1 675 MOVB R1, ret+16(FP) 676 RET 677 eq: 678 MOVV $1, R1 679 MOVB R1, ret+16(FP) 680 RET 681 682 // eqstring tests whether two strings are equal. 683 // The compiler guarantees that strings passed 684 // to eqstring have equal length. 685 // See runtime_test.go:eqstring_generic for 686 // equivalent Go code. 687 TEXT runtime·eqstring(SB),NOSPLIT,$0-33 688 MOVV s1_base+0(FP), R1 689 MOVV s2_base+16(FP), R2 690 MOVV $1, R3 691 MOVB R3, ret+32(FP) 692 BNE R1, R2, 2(PC) 693 RET 694 MOVV s1_len+8(FP), R3 695 ADDV R1, R3, R4 696 loop: 697 BNE R1, R4, 2(PC) 698 RET 699 MOVBU (R1), R6 700 ADDV $1, R1 701 MOVBU (R2), R7 702 ADDV $1, R2 703 BEQ R6, R7, loop 704 MOVB R0, ret+32(FP) 705 RET 706 707 // TODO: share code with memequal? 708 TEXT bytes·Equal(SB),NOSPLIT,$0-49 709 MOVV a_len+8(FP), R3 710 MOVV b_len+32(FP), R4 711 BNE R3, R4, noteq // unequal lengths are not equal 712 713 MOVV a+0(FP), R1 714 MOVV b+24(FP), R2 715 ADDV R1, R3 // end 716 717 loop: 718 BEQ R1, R3, equal // reached the end 719 MOVBU (R1), R6 720 ADDV $1, R1 721 MOVBU (R2), R7 722 ADDV $1, R2 723 BEQ R6, R7, loop 724 725 noteq: 726 MOVB R0, ret+48(FP) 727 RET 728 729 equal: 730 MOVV $1, R1 731 MOVB R1, ret+48(FP) 732 RET 733 734 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 735 MOVV s+0(FP), R1 736 MOVV s_len+8(FP), R2 737 MOVBU c+24(FP), R3 // byte to find 738 MOVV R1, R4 // store base for later 739 ADDV R1, R2 // end 740 ADDV $-1, R1 741 742 loop: 743 ADDV $1, R1 744 BEQ R1, R2, notfound 745 MOVBU (R1), R5 746 BNE R3, R5, loop 747 748 SUBV R4, R1 // remove base 749 MOVV R1, ret+32(FP) 750 RET 751 752 notfound: 753 MOVV $-1, R1 754 MOVV R1, ret+32(FP) 755 RET 756 757 TEXT strings·IndexByte(SB),NOSPLIT,$0-32 758 MOVV p+0(FP), R1 759 MOVV b_len+8(FP), R2 760 MOVBU c+16(FP), R3 // byte to find 761 MOVV R1, R4 // store base for later 762 ADDV R1, R2 // end 763 ADDV $-1, R1 764 765 loop: 766 ADDV $1, R1 767 BEQ R1, R2, notfound 768 MOVBU (R1), R5 769 BNE R3, R5, loop 770 771 SUBV R4, R1 // remove base 772 MOVV R1, ret+24(FP) 773 RET 774 775 notfound: 776 MOVV $-1, R1 777 MOVV R1, ret+24(FP) 778 RET 779 780 TEXT runtime·return0(SB), NOSPLIT, $0 781 MOVW $0, R1 782 RET 783 784 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 785 // Must obey the gcc calling convention. 786 TEXT _cgo_topofstack(SB),NOSPLIT,$16 787 // g (R30) and REGTMP (R23) might be clobbered by load_g. They 788 // are callee-save in the gcc calling convention, so save them. 789 MOVV R23, savedR23-16(SP) 790 MOVV g, savedG-8(SP) 791 792 JAL runtime·load_g(SB) 793 MOVV g_m(g), R1 794 MOVV m_curg(R1), R1 795 MOVV (g_stack+stack_hi)(R1), R2 // return value in R2 796 797 MOVV savedG-8(SP), g 798 MOVV savedR23-16(SP), R23 799 RET 800 801 // The top-most function running on a goroutine 802 // returns to goexit+PCQuantum. 803 TEXT runtime·goexit(SB),NOSPLIT,$-8-0 804 NOR R0, R0 // NOP 805 JAL runtime·goexit1(SB) // does not return 806 // traceback from goexit1 must hit code range of goexit 807 NOR R0, R0 // NOP 808 809 TEXT ·checkASM(SB),NOSPLIT,$0-1 810 MOVW $1, R1 811 MOVB R1, ret+0(FP) 812 RET