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