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