github.com/tidwall/go@v0.0.0-20170415222209-6694a6888b7d/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 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 631 // redirects to memhash(p, h, size) using the size 632 // stored in the closure. 633 TEXT runtime·memhash_varlen(SB),NOSPLIT,$16-12 634 GO_ARGS 635 NO_LOCAL_POINTERS 636 MOVW p+0(FP), R1 637 MOVW h+4(FP), R2 638 MOVW 4(REGCTXT), R3 639 MOVW R1, 4(R29) 640 MOVW R2, 8(R29) 641 MOVW R3, 12(R29) 642 JAL runtime·memhash(SB) 643 MOVW 16(R29), R1 644 MOVW R1, ret+8(FP) 645 RET 646 647 // Not implemented. 648 TEXT runtime·aeshash(SB),NOSPLIT,$0 649 UNDEF 650 651 // Not implemented. 652 TEXT runtime·aeshash32(SB),NOSPLIT,$0 653 UNDEF 654 655 // Not implemented. 656 TEXT runtime·aeshash64(SB),NOSPLIT,$0 657 UNDEF 658 659 // Not implemented. 660 TEXT runtime·aeshashstr(SB),NOSPLIT,$0 661 UNDEF 662 663 // memequal(a, b unsafe.Pointer, size uintptr) bool 664 TEXT runtime·memequal(SB),NOSPLIT,$0-13 665 MOVW a+0(FP), R1 666 MOVW b+4(FP), R2 667 BEQ R1, R2, eq 668 MOVW size+8(FP), R3 669 ADDU R1, R3, R4 670 loop: 671 BNE R1, R4, test 672 MOVW $1, R1 673 MOVB R1, ret+12(FP) 674 RET 675 test: 676 MOVBU (R1), R6 677 ADDU $1, R1 678 MOVBU (R2), R7 679 ADDU $1, R2 680 BEQ R6, R7, loop 681 682 MOVB R0, ret+12(FP) 683 RET 684 eq: 685 MOVW $1, R1 686 MOVB R1, ret+12(FP) 687 RET 688 689 // memequal_varlen(a, b unsafe.Pointer) bool 690 TEXT runtime·memequal_varlen(SB),NOSPLIT,$0-9 691 MOVW a+0(FP), R1 692 MOVW b+4(FP), R2 693 BEQ R1, R2, eq 694 MOVW 4(REGCTXT), R3 // compiler stores size at offset 4 in the closure 695 ADDU R1, R3, R4 696 loop: 697 BNE R1, R4, test 698 MOVW $1, R1 699 MOVB R1, ret+8(FP) 700 RET 701 test: 702 MOVBU (R1), R6 703 ADDU $1, R1 704 MOVBU (R2), R7 705 ADDU $1, R2 706 BEQ R6, R7, loop 707 708 MOVB R0, ret+8(FP) 709 RET 710 eq: 711 MOVW $1, R1 712 MOVB R1, ret+8(FP) 713 RET 714 715 // eqstring tests whether two strings are equal. 716 // The compiler guarantees that strings passed 717 // to eqstring have equal length. 718 // See runtime_test.go:eqstring_generic for 719 // equivalent Go code. 720 TEXT runtime·eqstring(SB),NOSPLIT,$0-17 721 MOVW s1_base+0(FP), R1 722 MOVW s2_base+8(FP), R2 723 MOVW $1, R3 724 MOVBU R3, ret+16(FP) 725 BNE R1, R2, 2(PC) 726 RET 727 MOVW s1_len+4(FP), R3 728 ADDU R1, R3, R4 729 loop: 730 BNE R1, R4, 2(PC) 731 RET 732 MOVBU (R1), R6 733 ADDU $1, R1 734 MOVBU (R2), R7 735 ADDU $1, R2 736 BEQ R6, R7, loop 737 MOVB R0, ret+16(FP) 738 RET 739 740 TEXT bytes·Equal(SB),NOSPLIT,$0-25 741 MOVW a_len+4(FP), R3 742 MOVW b_len+16(FP), R4 743 BNE R3, R4, noteq // unequal lengths are not equal 744 745 MOVW a+0(FP), R1 746 MOVW b+12(FP), R2 747 ADDU R1, R3 // end 748 749 loop: 750 BEQ R1, R3, equal // reached the end 751 MOVBU (R1), R6 752 ADDU $1, R1 753 MOVBU (R2), R7 754 ADDU $1, R2 755 BEQ R6, R7, loop 756 757 noteq: 758 MOVB R0, ret+24(FP) 759 RET 760 761 equal: 762 MOVW $1, R1 763 MOVB R1, ret+24(FP) 764 RET 765 766 TEXT bytes·IndexByte(SB),NOSPLIT,$0-20 767 MOVW s+0(FP), R1 768 MOVW s_len+4(FP), R2 769 MOVBU c+12(FP), R3 // byte to find 770 ADDU $1, R1, R4 // store base+1 for later 771 ADDU R1, R2 // end 772 773 loop: 774 BEQ R1, R2, notfound 775 MOVBU (R1), R5 776 ADDU $1, R1 777 BNE R3, R5, loop 778 779 SUBU R4, R1 // R1 will be one beyond the position we want so remove (base+1) 780 MOVW R1, ret+16(FP) 781 RET 782 783 notfound: 784 MOVW $-1, R1 785 MOVW R1, ret+16(FP) 786 RET 787 788 TEXT strings·IndexByte(SB),NOSPLIT,$0-16 789 MOVW s_base+0(FP), R1 790 MOVW s_len+4(FP), R2 791 MOVBU c+8(FP), R3 // byte to find 792 ADDU $1, R1, R4 // store base+1 for later 793 ADDU R1, R2 // end 794 795 loop: 796 BEQ R1, R2, notfound 797 MOVBU (R1), R5 798 ADDU $1, R1 799 BNE R3, R5, loop 800 801 SUBU R4, R1 // remove (base+1) 802 MOVW R1, ret+12(FP) 803 RET 804 805 notfound: 806 MOVW $-1, R1 807 MOVW R1, ret+12(FP) 808 RET 809 810 TEXT runtime·cmpstring(SB),NOSPLIT,$0-20 811 MOVW s1_base+0(FP), R3 812 MOVW s1_len+4(FP), R1 813 MOVW s2_base+8(FP), R4 814 MOVW s2_len+12(FP), R2 815 BEQ R3, R4, samebytes 816 SGTU R1, R2, R7 817 MOVW R1, R8 818 CMOVN R7, R2, R8 // R8 is min(R1, R2) 819 820 ADDU R3, R8 // R3 is current byte in s1, R8 is last byte in s1 to compare 821 loop: 822 BEQ R3, R8, samebytes // all compared bytes were the same; compare lengths 823 824 MOVBU (R3), R6 825 ADDU $1, R3 826 MOVBU (R4), R7 827 ADDU $1, R4 828 BEQ R6, R7 , loop 829 // bytes differed 830 SGTU R6, R7, R8 831 MOVW $-1, R6 832 CMOVZ R8, R6, R8 833 JMP cmp_ret 834 samebytes: 835 SGTU R1, R2, R6 836 SGTU R2, R1, R7 837 SUBU R7, R6, R8 838 cmp_ret: 839 MOVW R8, ret+16(FP) 840 RET 841 842 TEXT bytes·Compare(SB),NOSPLIT,$0-28 843 MOVW s1_base+0(FP), R3 844 MOVW s2_base+12(FP), R4 845 MOVW s1_len+4(FP), R1 846 MOVW s2_len+16(FP), R2 847 BEQ R3, R4, samebytes 848 SGTU R1, R2, R7 849 MOVW R1, R8 850 CMOVN R7, R2, R8 // R8 is min(R1, R2) 851 852 ADDU R3, R8 // R3 is current byte in s1, R8 is last byte in s1 to compare 853 loop: 854 BEQ R3, R8, samebytes 855 856 MOVBU (R3), R6 857 ADDU $1, R3 858 MOVBU (R4), R7 859 ADDU $1, R4 860 BEQ R6, R7 , loop 861 862 SGTU R6, R7, R8 863 MOVW $-1, R6 864 CMOVZ R8, R6, R8 865 JMP cmp_ret 866 samebytes: 867 SGTU R1, R2, R6 868 SGTU R2, R1, R7 869 SUBU R7, R6, R8 870 cmp_ret: 871 MOVW R8, ret+24(FP) 872 RET 873 874 TEXT runtime·return0(SB),NOSPLIT,$0 875 MOVW $0, R1 876 RET 877 878 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 879 // Must obey the gcc calling convention. 880 TEXT _cgo_topofstack(SB),NOSPLIT,$-4 881 // g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23 882 // are callee-save in the gcc calling convention, so save them. 883 MOVW R23, R8 884 MOVW g, R9 885 MOVW R31, R10 // this call frame does not save LR 886 887 JAL runtime·load_g(SB) 888 MOVW g_m(g), R1 889 MOVW m_curg(R1), R1 890 MOVW (g_stack+stack_hi)(R1), R2 // return value in R2 891 892 MOVW R8, R23 893 MOVW R9, g 894 MOVW R10, R31 895 896 RET 897 898 // The top-most function running on a goroutine 899 // returns to goexit+PCQuantum. 900 TEXT runtime·goexit(SB),NOSPLIT,$-4-0 901 NOR R0, R0 // NOP 902 JAL runtime·goexit1(SB) // does not return 903 // traceback from goexit1 must hit code range of goexit 904 NOR R0, R0 // NOP 905 906 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-4 907 RET 908 909 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-4 910 RET 911 912 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-4 913 RET 914 915 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-4 916 RET 917 918 TEXT ·checkASM(SB),NOSPLIT,$0-1 919 MOVW $1, R1 920 MOVB R1, ret+0(FP) 921 RET