github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/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|NOFRAME,$0-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|NOFRAME,$0-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 JAL runtime·abort(SB) 184 185 switch: 186 // save our state in g->sched. Pretend to 187 // be systemstack_switch if the G stack is scanned. 188 MOVW $runtime·systemstack_switch(SB), R4 189 ADDU $8, R4 // get past prologue 190 MOVW R4, (g_sched+gobuf_pc)(g) 191 MOVW R29, (g_sched+gobuf_sp)(g) 192 MOVW R0, (g_sched+gobuf_lr)(g) 193 MOVW g, (g_sched+gobuf_g)(g) 194 195 // switch to g0 196 MOVW R3, g 197 JAL runtime·save_g(SB) 198 MOVW (g_sched+gobuf_sp)(g), R1 199 // make it look like mstart called systemstack on g0, to stop traceback 200 ADDU $-4, R1 201 MOVW $runtime·mstart(SB), R2 202 MOVW R2, 0(R1) 203 MOVW R1, R29 204 205 // call target function 206 MOVW 0(REGCTXT), R4 // code pointer 207 JAL (R4) 208 209 // switch back to g 210 MOVW g_m(g), R1 211 MOVW m_curg(R1), g 212 JAL runtime·save_g(SB) 213 MOVW (g_sched+gobuf_sp)(g), R29 214 MOVW R0, (g_sched+gobuf_sp)(g) 215 RET 216 217 noswitch: 218 // already on m stack, just call directly 219 // Using a tail call here cleans up tracebacks since we won't stop 220 // at an intermediate systemstack. 221 MOVW 0(REGCTXT), R4 // code pointer 222 MOVW 0(R29), R31 // restore LR 223 ADD $4, R29 224 JMP (R4) 225 226 /* 227 * support for morestack 228 */ 229 230 // Called during function prolog when more stack is needed. 231 // Caller has already loaded: 232 // R1: framesize, R2: argsize, R3: LR 233 // 234 // The traceback routines see morestack on a g0 as being 235 // the top of a stack (for example, morestack calling newstack 236 // calling the scheduler calling newm calling gc), so we must 237 // record an argument size. For that purpose, it has no arguments. 238 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 239 // Cannot grow scheduler stack (m->g0). 240 MOVW g_m(g), R7 241 MOVW m_g0(R7), R8 242 BNE g, R8, 3(PC) 243 JAL runtime·badmorestackg0(SB) 244 JAL runtime·abort(SB) 245 246 // Cannot grow signal stack (m->gsignal). 247 MOVW m_gsignal(R7), R8 248 BNE g, R8, 3(PC) 249 JAL runtime·badmorestackgsignal(SB) 250 JAL runtime·abort(SB) 251 252 // Called from f. 253 // Set g->sched to context in f. 254 MOVW R29, (g_sched+gobuf_sp)(g) 255 MOVW R31, (g_sched+gobuf_pc)(g) 256 MOVW R3, (g_sched+gobuf_lr)(g) 257 MOVW REGCTXT, (g_sched+gobuf_ctxt)(g) 258 259 // Called from f. 260 // Set m->morebuf to f's caller. 261 MOVW R3, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 262 MOVW R29, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 263 MOVW g, (m_morebuf+gobuf_g)(R7) 264 265 // Call newstack on m->g0's stack. 266 MOVW m_g0(R7), g 267 JAL runtime·save_g(SB) 268 MOVW (g_sched+gobuf_sp)(g), R29 269 // Create a stack frame on g0 to call newstack. 270 MOVW R0, -4(R29) // Zero saved LR in frame 271 ADDU $-4, R29 272 JAL runtime·newstack(SB) 273 274 // Not reached, but make sure the return PC from the call to newstack 275 // is still in this function, and not the beginning of the next. 276 UNDEF 277 278 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0 279 MOVW R0, REGCTXT 280 JMP runtime·morestack(SB) 281 282 // reflectcall: call a function with the given argument list 283 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 284 // we don't have variable-sized frames, so we use a small number 285 // of constant-sized-frame functions to encode a few bits of size in the pc. 286 287 #define DISPATCH(NAME,MAXSIZE) \ 288 MOVW $MAXSIZE, R23; \ 289 SGTU R1, R23, R23; \ 290 BNE R23, 3(PC); \ 291 MOVW $NAME(SB), R4; \ 292 JMP (R4) 293 294 TEXT reflect·call(SB),NOSPLIT,$0-20 295 JMP ·reflectcall(SB) 296 297 TEXT ·reflectcall(SB),NOSPLIT|NOFRAME,$0-20 298 MOVW argsize+12(FP), R1 299 300 DISPATCH(runtime·call16, 16) 301 DISPATCH(runtime·call32, 32) 302 DISPATCH(runtime·call64, 64) 303 DISPATCH(runtime·call128, 128) 304 DISPATCH(runtime·call256, 256) 305 DISPATCH(runtime·call512, 512) 306 DISPATCH(runtime·call1024, 1024) 307 DISPATCH(runtime·call2048, 2048) 308 DISPATCH(runtime·call4096, 4096) 309 DISPATCH(runtime·call8192, 8192) 310 DISPATCH(runtime·call16384, 16384) 311 DISPATCH(runtime·call32768, 32768) 312 DISPATCH(runtime·call65536, 65536) 313 DISPATCH(runtime·call131072, 131072) 314 DISPATCH(runtime·call262144, 262144) 315 DISPATCH(runtime·call524288, 524288) 316 DISPATCH(runtime·call1048576, 1048576) 317 DISPATCH(runtime·call2097152, 2097152) 318 DISPATCH(runtime·call4194304, 4194304) 319 DISPATCH(runtime·call8388608, 8388608) 320 DISPATCH(runtime·call16777216, 16777216) 321 DISPATCH(runtime·call33554432, 33554432) 322 DISPATCH(runtime·call67108864, 67108864) 323 DISPATCH(runtime·call134217728, 134217728) 324 DISPATCH(runtime·call268435456, 268435456) 325 DISPATCH(runtime·call536870912, 536870912) 326 DISPATCH(runtime·call1073741824, 1073741824) 327 MOVW $runtime·badreflectcall(SB), R4 328 JMP (R4) 329 330 #define CALLFN(NAME,MAXSIZE) \ 331 TEXT NAME(SB),WRAPPER,$MAXSIZE-20; \ 332 NO_LOCAL_POINTERS; \ 333 /* copy arguments to stack */ \ 334 MOVW arg+8(FP), R1; \ 335 MOVW argsize+12(FP), R2; \ 336 MOVW R29, R3; \ 337 ADDU $4, R3; \ 338 ADDU R3, R2; \ 339 BEQ R3, R2, 6(PC); \ 340 MOVBU (R1), R4; \ 341 ADDU $1, R1; \ 342 MOVBU R4, (R3); \ 343 ADDU $1, R3; \ 344 JMP -5(PC); \ 345 /* call function */ \ 346 MOVW f+4(FP), REGCTXT; \ 347 MOVW (REGCTXT), R4; \ 348 PCDATA $PCDATA_StackMapIndex, $0; \ 349 JAL (R4); \ 350 /* copy return values back */ \ 351 MOVW argtype+0(FP), R5; \ 352 MOVW arg+8(FP), R1; \ 353 MOVW n+12(FP), R2; \ 354 MOVW retoffset+16(FP), R4; \ 355 ADDU $4, R29, R3; \ 356 ADDU R4, R3; \ 357 ADDU R4, R1; \ 358 SUBU R4, R2; \ 359 JAL callRet<>(SB); \ 360 RET 361 362 // callRet copies return values back at the end of call*. This is a 363 // separate function so it can allocate stack space for the arguments 364 // to reflectcallmove. It does not follow the Go ABI; it expects its 365 // arguments in registers. 366 TEXT callRet<>(SB), NOSPLIT, $16-0 367 MOVW R5, 4(R29) 368 MOVW R1, 8(R29) 369 MOVW R3, 12(R29) 370 MOVW R2, 16(R29) 371 JAL runtime·reflectcallmove(SB) 372 RET 373 374 CALLFN(·call16, 16) 375 CALLFN(·call32, 32) 376 CALLFN(·call64, 64) 377 CALLFN(·call128, 128) 378 CALLFN(·call256, 256) 379 CALLFN(·call512, 512) 380 CALLFN(·call1024, 1024) 381 CALLFN(·call2048, 2048) 382 CALLFN(·call4096, 4096) 383 CALLFN(·call8192, 8192) 384 CALLFN(·call16384, 16384) 385 CALLFN(·call32768, 32768) 386 CALLFN(·call65536, 65536) 387 CALLFN(·call131072, 131072) 388 CALLFN(·call262144, 262144) 389 CALLFN(·call524288, 524288) 390 CALLFN(·call1048576, 1048576) 391 CALLFN(·call2097152, 2097152) 392 CALLFN(·call4194304, 4194304) 393 CALLFN(·call8388608, 8388608) 394 CALLFN(·call16777216, 16777216) 395 CALLFN(·call33554432, 33554432) 396 CALLFN(·call67108864, 67108864) 397 CALLFN(·call134217728, 134217728) 398 CALLFN(·call268435456, 268435456) 399 CALLFN(·call536870912, 536870912) 400 CALLFN(·call1073741824, 1073741824) 401 402 TEXT runtime·procyield(SB),NOSPLIT,$0-4 403 RET 404 405 // void jmpdefer(fv, sp); 406 // called from deferreturn. 407 // 1. grab stored LR for caller 408 // 2. sub 8 bytes to get back to JAL deferreturn 409 // 3. JMP to fn 410 TEXT runtime·jmpdefer(SB),NOSPLIT,$0-8 411 MOVW 0(R29), R31 412 ADDU $-8, R31 413 414 MOVW fv+0(FP), REGCTXT 415 MOVW argp+4(FP), R29 416 ADDU $-4, R29 417 NOR R0, R0 // prevent scheduling 418 MOVW 0(REGCTXT), R4 419 JMP (R4) 420 421 // Save state of caller into g->sched. Smashes R1. 422 TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 423 MOVW R31, (g_sched+gobuf_pc)(g) 424 MOVW R29, (g_sched+gobuf_sp)(g) 425 MOVW R0, (g_sched+gobuf_lr)(g) 426 MOVW R0, (g_sched+gobuf_ret)(g) 427 // Assert ctxt is zero. See func save. 428 MOVW (g_sched+gobuf_ctxt)(g), R1 429 BEQ R1, 2(PC) 430 JAL runtime·badctxt(SB) 431 RET 432 433 // func asmcgocall(fn, arg unsafe.Pointer) int32 434 // Call fn(arg) on the scheduler stack, 435 // aligned appropriately for the gcc ABI. 436 // See cgocall.go for more details. 437 TEXT ·asmcgocall(SB),NOSPLIT,$0-12 438 MOVW fn+0(FP), R25 439 MOVW arg+4(FP), R4 440 441 MOVW R29, R3 // save original stack pointer 442 MOVW g, R2 443 444 // Figure out if we need to switch to m->g0 stack. 445 // We get called to create new OS threads too, and those 446 // come in on the m->g0 stack already. 447 MOVW g_m(g), R5 448 MOVW m_g0(R5), R6 449 BEQ R6, g, g0 450 451 JAL gosave<>(SB) 452 MOVW R6, g 453 JAL runtime·save_g(SB) 454 MOVW (g_sched+gobuf_sp)(g), R29 455 456 // Now on a scheduling stack (a pthread-created stack). 457 g0: 458 // Save room for two of our pointers and O32 frame. 459 ADDU $-24, R29 460 AND $~7, R29 // O32 ABI expects 8-byte aligned stack on function entry 461 MOVW R2, 16(R29) // save old g on stack 462 MOVW (g_stack+stack_hi)(R2), R2 463 SUBU R3, R2 464 MOVW R2, 20(R29) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 465 JAL (R25) 466 467 // Restore g, stack pointer. R2 is return value. 468 MOVW 16(R29), g 469 JAL runtime·save_g(SB) 470 MOVW (g_stack+stack_hi)(g), R5 471 MOVW 20(R29), R6 472 SUBU R6, R5 473 MOVW R5, R29 474 475 MOVW R2, ret+8(FP) 476 RET 477 478 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 479 // Turn the fn into a Go func (by taking its address) and call 480 // cgocallback_gofunc. 481 TEXT runtime·cgocallback(SB),NOSPLIT,$16-16 482 MOVW $fn+0(FP), R1 483 MOVW R1, 4(R29) 484 MOVW frame+4(FP), R1 485 MOVW R1, 8(R29) 486 MOVW framesize+8(FP), R1 487 MOVW R1, 12(R29) 488 MOVW ctxt+12(FP), R1 489 MOVW R1, 16(R29) 490 MOVW $runtime·cgocallback_gofunc(SB), R1 491 JAL (R1) 492 RET 493 494 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 495 // See cgocall.go for more details. 496 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$8-16 497 NO_LOCAL_POINTERS 498 499 // Load m and g from thread-local storage. 500 MOVB runtime·iscgo(SB), R1 501 BEQ R1, nocgo 502 JAL runtime·load_g(SB) 503 nocgo: 504 505 // If g is nil, Go did not create the current thread. 506 // Call needm to obtain one for temporary use. 507 // In this case, we're running on the thread stack, so there's 508 // lots of space, but the linker doesn't know. Hide the call from 509 // the linker analysis by using an indirect call. 510 BEQ g, needm 511 512 MOVW g_m(g), R3 513 MOVW R3, savedm-4(SP) 514 JMP havem 515 516 needm: 517 MOVW g, savedm-4(SP) // g is zero, so is m. 518 MOVW $runtime·needm(SB), R4 519 JAL (R4) 520 521 // Set m->sched.sp = SP, so that if a panic happens 522 // during the function we are about to execute, it will 523 // have a valid SP to run on the g0 stack. 524 // The next few lines (after the havem label) 525 // will save this SP onto the stack and then write 526 // the same SP back to m->sched.sp. That seems redundant, 527 // but if an unrecovered panic happens, unwindm will 528 // restore the g->sched.sp from the stack location 529 // and then systemstack will try to use it. If we don't set it here, 530 // that restored SP will be uninitialized (typically 0) and 531 // will not be usable. 532 MOVW g_m(g), R3 533 MOVW m_g0(R3), R1 534 MOVW R29, (g_sched+gobuf_sp)(R1) 535 536 havem: 537 // Now there's a valid m, and we're running on its m->g0. 538 // Save current m->g0->sched.sp on stack and then set it to SP. 539 // Save current sp in m->g0->sched.sp in preparation for 540 // switch back to m->curg stack. 541 // NOTE: unwindm knows that the saved g->sched.sp is at 4(R29) aka savedsp-8(SP). 542 MOVW m_g0(R3), R1 543 MOVW (g_sched+gobuf_sp)(R1), R2 544 MOVW R2, savedsp-8(SP) 545 MOVW R29, (g_sched+gobuf_sp)(R1) 546 547 // Switch to m->curg stack and call runtime.cgocallbackg. 548 // Because we are taking over the execution of m->curg 549 // but *not* resuming what had been running, we need to 550 // save that information (m->curg->sched) so we can restore it. 551 // We can restore m->curg->sched.sp easily, because calling 552 // runtime.cgocallbackg leaves SP unchanged upon return. 553 // To save m->curg->sched.pc, we push it onto the stack. 554 // This has the added benefit that it looks to the traceback 555 // routine like cgocallbackg is going to return to that 556 // PC (because the frame we allocate below has the same 557 // size as cgocallback_gofunc's frame declared above) 558 // so that the traceback will seamlessly trace back into 559 // the earlier calls. 560 // 561 // In the new goroutine, -4(SP) is unused (where SP refers to 562 // m->curg's SP while we're setting it up, before we've adjusted it). 563 MOVW m_curg(R3), g 564 JAL runtime·save_g(SB) 565 MOVW (g_sched+gobuf_sp)(g), R2 // prepare stack as R2 566 MOVW (g_sched+gobuf_pc)(g), R4 567 MOVW R4, -12(R2) 568 MOVW ctxt+12(FP), R1 569 MOVW R1, -8(R2) 570 MOVW $-12(R2), R29 571 JAL runtime·cgocallbackg(SB) 572 573 // Restore g->sched (== m->curg->sched) from saved values. 574 MOVW 0(R29), R4 575 MOVW R4, (g_sched+gobuf_pc)(g) 576 MOVW $12(R29), R2 577 MOVW R2, (g_sched+gobuf_sp)(g) 578 579 // Switch back to m->g0's stack and restore m->g0->sched.sp. 580 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 581 // so we do not have to restore it.) 582 MOVW g_m(g), R3 583 MOVW m_g0(R3), g 584 JAL runtime·save_g(SB) 585 MOVW (g_sched+gobuf_sp)(g), R29 586 MOVW savedsp-8(SP), R2 587 MOVW R2, (g_sched+gobuf_sp)(g) 588 589 // If the m on entry was nil, we called needm above to borrow an m 590 // for the duration of the call. Since the call is over, return it with dropm. 591 MOVW savedm-4(SP), R3 592 BNE R3, droppedm 593 MOVW $runtime·dropm(SB), R4 594 JAL (R4) 595 droppedm: 596 597 // Done! 598 RET 599 600 // void setg(G*); set g. for use by needm. 601 // This only happens if iscgo, so jump straight to save_g 602 TEXT runtime·setg(SB),NOSPLIT,$0-4 603 MOVW gg+0(FP), g 604 JAL runtime·save_g(SB) 605 RET 606 607 // void setg_gcc(G*); set g in C TLS. 608 // Must obey the gcc calling convention. 609 TEXT setg_gcc<>(SB),NOSPLIT,$0 610 MOVW R4, g 611 JAL runtime·save_g(SB) 612 RET 613 614 TEXT runtime·abort(SB),NOSPLIT,$0-0 615 UNDEF 616 617 // Not implemented. 618 TEXT runtime·aeshash(SB),NOSPLIT,$0 619 UNDEF 620 621 // Not implemented. 622 TEXT runtime·aeshash32(SB),NOSPLIT,$0 623 UNDEF 624 625 // Not implemented. 626 TEXT runtime·aeshash64(SB),NOSPLIT,$0 627 UNDEF 628 629 // Not implemented. 630 TEXT runtime·aeshashstr(SB),NOSPLIT,$0 631 UNDEF 632 633 TEXT runtime·return0(SB),NOSPLIT,$0 634 MOVW $0, R1 635 RET 636 637 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 638 // Must obey the gcc calling convention. 639 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 640 // g (R30), R3 and REGTMP (R23) might be clobbered by load_g. R30 and R23 641 // are callee-save in the gcc calling convention, so save them. 642 MOVW R23, R8 643 MOVW g, R9 644 MOVW R31, R10 // this call frame does not save LR 645 646 JAL runtime·load_g(SB) 647 MOVW g_m(g), R1 648 MOVW m_curg(R1), R1 649 MOVW (g_stack+stack_hi)(R1), R2 // return value in R2 650 651 MOVW R8, R23 652 MOVW R9, g 653 MOVW R10, R31 654 655 RET 656 657 // The top-most function running on a goroutine 658 // returns to goexit+PCQuantum. 659 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0 660 NOR R0, R0 // NOP 661 JAL runtime·goexit1(SB) // does not return 662 // traceback from goexit1 must hit code range of goexit 663 NOR R0, R0 // NOP 664 665 TEXT ·checkASM(SB),NOSPLIT,$0-1 666 MOVW $1, R1 667 MOVB R1, ret+0(FP) 668 RET 669 670 // gcWriteBarrier performs a heap pointer write and informs the GC. 671 // 672 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 673 // - R20 is the destination of the write 674 // - R21 is the value being written at R20. 675 // It clobbers R23 (the linker temp register). 676 // The act of CALLing gcWriteBarrier will clobber R31 (LR). 677 // It does not clobber any other general-purpose registers, 678 // but may clobber others (e.g., floating point registers). 679 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104 680 // Save the registers clobbered by the fast path. 681 MOVW R1, 100(R29) 682 MOVW R2, 104(R29) 683 MOVW g_m(g), R1 684 MOVW m_p(R1), R1 685 MOVW (p_wbBuf+wbBuf_next)(R1), R2 686 // Increment wbBuf.next position. 687 ADD $8, R2 688 MOVW R2, (p_wbBuf+wbBuf_next)(R1) 689 MOVW (p_wbBuf+wbBuf_end)(R1), R1 690 MOVW R1, R23 // R23 is linker temp register 691 // Record the write. 692 MOVW R21, -8(R2) // Record value 693 MOVW (R20), R1 // TODO: This turns bad writes into bad reads. 694 MOVW R1, -4(R2) // Record *slot 695 // Is the buffer full? 696 BEQ R2, R23, flush 697 ret: 698 MOVW 100(R29), R1 699 MOVW 104(R29), R2 700 // Do the write. 701 MOVW R21, (R20) 702 RET 703 704 flush: 705 // Save all general purpose registers since these could be 706 // clobbered by wbBufFlush and were not saved by the caller. 707 MOVW R20, 4(R29) // Also first argument to wbBufFlush 708 MOVW R21, 8(R29) // Also second argument to wbBufFlush 709 // R1 already saved 710 // R2 already saved 711 MOVW R3, 12(R29) 712 MOVW R4, 16(R29) 713 MOVW R5, 20(R29) 714 MOVW R6, 24(R29) 715 MOVW R7, 28(R29) 716 MOVW R8, 32(R29) 717 MOVW R9, 36(R29) 718 MOVW R10, 40(R29) 719 MOVW R11, 44(R29) 720 MOVW R12, 48(R29) 721 MOVW R13, 52(R29) 722 MOVW R14, 56(R29) 723 MOVW R15, 60(R29) 724 MOVW R16, 64(R29) 725 MOVW R17, 68(R29) 726 MOVW R18, 72(R29) 727 MOVW R19, 76(R29) 728 MOVW R20, 80(R29) 729 // R21 already saved 730 // R22 already saved. 731 MOVW R22, 84(R29) 732 // R23 is tmp register. 733 MOVW R24, 88(R29) 734 MOVW R25, 92(R29) 735 // R26 is reserved by kernel. 736 // R27 is reserved by kernel. 737 MOVW R28, 96(R29) 738 // R29 is SP. 739 // R30 is g. 740 // R31 is LR, which was saved by the prologue. 741 742 // This takes arguments R20 and R21. 743 CALL runtime·wbBufFlush(SB) 744 745 MOVW 4(R29), R20 746 MOVW 8(R29), R21 747 MOVW 12(R29), R3 748 MOVW 16(R29), R4 749 MOVW 20(R29), R5 750 MOVW 24(R29), R6 751 MOVW 28(R29), R7 752 MOVW 32(R29), R8 753 MOVW 36(R29), R9 754 MOVW 40(R29), R10 755 MOVW 44(R29), R11 756 MOVW 48(R29), R12 757 MOVW 52(R29), R13 758 MOVW 56(R29), R14 759 MOVW 60(R29), R15 760 MOVW 64(R29), R16 761 MOVW 68(R29), R17 762 MOVW 72(R29), R18 763 MOVW 76(R29), R19 764 MOVW 80(R29), R20 765 MOVW 84(R29), R22 766 MOVW 88(R29), R24 767 MOVW 92(R29), R25 768 MOVW 96(R29), R28 769 JMP ret