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