github.com/fjballest/golang@v0.0.0-20151209143359-e4c5fe594ca8/src/runtime/asm_ppc64x.s (about) 1 // Copyright 2014 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 ppc64 ppc64le 6 7 #include "go_asm.h" 8 #include "go_tls.h" 9 #include "funcdata.h" 10 #include "textflag.h" 11 #include "asm_ppc64x.h" 12 13 TEXT runtime·rt0_go(SB),NOSPLIT,$0 14 // R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer 15 16 // initialize essential registers 17 BL runtime·reginit(SB) 18 19 SUB $(FIXED_FRAME+16), R1 20 MOVD R2, 24(R1) // stash the TOC pointer away again now we've created a new frame 21 MOVW R3, FIXED_FRAME+0(R1) // argc 22 MOVD R4, FIXED_FRAME+8(R1) // argv 23 24 // create istack out of the given (operating system) stack. 25 // _cgo_init may update stackguard. 26 MOVD $runtime·g0(SB), g 27 MOVD $(-64*1024), R31 28 ADD R31, R1, R3 29 MOVD R3, g_stackguard0(g) 30 MOVD R3, g_stackguard1(g) 31 MOVD R3, (g_stack+stack_lo)(g) 32 MOVD R1, (g_stack+stack_hi)(g) 33 34 // if there is a _cgo_init, call it using the gcc ABI. 35 MOVD _cgo_init(SB), R12 36 CMP R0, R12 37 BEQ nocgo 38 MOVD R12, CTR // r12 = "global function entry point" 39 MOVD R13, R5 // arg 2: TLS base pointer 40 MOVD $setg_gcc<>(SB), R4 // arg 1: setg 41 MOVD g, R3 // arg 0: G 42 // C functions expect 32 bytes of space on caller stack frame 43 // and a 16-byte aligned R1 44 MOVD R1, R14 // save current stack 45 SUB $32, R1 // reserve 32 bytes 46 RLDCR $0, R1, $~15, R1 // 16-byte align 47 BL (CTR) // may clobber R0, R3-R12 48 MOVD R14, R1 // restore stack 49 MOVD 24(R1), R2 50 XOR R0, R0 // fix R0 51 52 nocgo: 53 // update stackguard after _cgo_init 54 MOVD (g_stack+stack_lo)(g), R3 55 ADD $const__StackGuard, R3 56 MOVD R3, g_stackguard0(g) 57 MOVD R3, g_stackguard1(g) 58 59 // set the per-goroutine and per-mach "registers" 60 MOVD $runtime·m0(SB), R3 61 62 // save m->g0 = g0 63 MOVD g, m_g0(R3) 64 // save m0 to g0->m 65 MOVD R3, g_m(g) 66 67 BL runtime·check(SB) 68 69 // args are already prepared 70 BL runtime·args(SB) 71 BL runtime·osinit(SB) 72 BL runtime·schedinit(SB) 73 74 // create a new goroutine to start program 75 MOVD $runtime·mainPC(SB), R3 // entry 76 MOVDU R3, -8(R1) 77 MOVDU R0, -8(R1) 78 MOVDU R0, -8(R1) 79 MOVDU R0, -8(R1) 80 MOVDU R0, -8(R1) 81 MOVDU R0, -8(R1) 82 BL runtime·newproc(SB) 83 ADD $(16+FIXED_FRAME), R1 84 85 // start this M 86 BL runtime·mstart(SB) 87 88 MOVD R0, 1(R0) 89 RET 90 91 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 92 GLOBL runtime·mainPC(SB),RODATA,$8 93 94 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 95 MOVD R0, 2(R0) // TODO: TD 96 RET 97 98 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 99 RET 100 101 TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0 102 // crosscall_ppc64 and crosscall2 need to reginit, but can't 103 // get at the 'runtime.reginit' symbol. 104 BR runtime·reginit(SB) 105 106 TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0 107 // set R0 to zero, it's expected by the toolchain 108 XOR R0, R0 109 // initialize essential FP registers 110 FMOVD $4503601774854144.0, F27 111 FMOVD $0.5, F29 112 FSUB F29, F29, F28 113 FADD F29, F29, F30 114 FADD F30, F30, F31 115 RET 116 117 /* 118 * go-routine 119 */ 120 121 // void gosave(Gobuf*) 122 // save state in Gobuf; setjmp 123 TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8 124 MOVD buf+0(FP), R3 125 MOVD R1, gobuf_sp(R3) 126 MOVD LR, R31 127 MOVD R31, gobuf_pc(R3) 128 MOVD g, gobuf_g(R3) 129 MOVD R0, gobuf_lr(R3) 130 MOVD R0, gobuf_ret(R3) 131 MOVD R0, gobuf_ctxt(R3) 132 RET 133 134 // void gogo(Gobuf*) 135 // restore state from Gobuf; longjmp 136 TEXT runtime·gogo(SB), NOSPLIT|NOFRAME, $0-8 137 MOVD buf+0(FP), R5 138 MOVD gobuf_g(R5), g // make sure g is not nil 139 BL runtime·save_g(SB) 140 141 MOVD 0(g), R4 142 MOVD gobuf_sp(R5), R1 143 MOVD gobuf_lr(R5), R31 144 MOVD R31, LR 145 MOVD gobuf_ret(R5), R3 146 MOVD gobuf_ctxt(R5), R11 147 MOVD R0, gobuf_sp(R5) 148 MOVD R0, gobuf_ret(R5) 149 MOVD R0, gobuf_lr(R5) 150 MOVD R0, gobuf_ctxt(R5) 151 CMP R0, R0 // set condition codes for == test, needed by stack split 152 MOVD gobuf_pc(R5), R12 153 MOVD R12, CTR 154 BR (CTR) 155 156 // void mcall(fn func(*g)) 157 // Switch to m->g0's stack, call fn(g). 158 // Fn must never return. It should gogo(&g->sched) 159 // to keep running g. 160 TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 161 // Save caller state in g->sched 162 MOVD R1, (g_sched+gobuf_sp)(g) 163 MOVD LR, R31 164 MOVD R31, (g_sched+gobuf_pc)(g) 165 MOVD R0, (g_sched+gobuf_lr)(g) 166 MOVD g, (g_sched+gobuf_g)(g) 167 168 // Switch to m->g0 & its stack, call fn. 169 MOVD g, R3 170 MOVD g_m(g), R8 171 MOVD m_g0(R8), g 172 BL runtime·save_g(SB) 173 CMP g, R3 174 BNE 2(PC) 175 BR runtime·badmcall(SB) 176 MOVD fn+0(FP), R11 // context 177 MOVD 0(R11), R12 // code pointer 178 MOVD R12, CTR 179 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp 180 MOVDU R3, -8(R1) 181 MOVDU R0, -8(R1) 182 MOVDU R0, -8(R1) 183 MOVDU R0, -8(R1) 184 MOVDU R0, -8(R1) 185 BL (CTR) 186 MOVD 24(R1), R2 187 BR runtime·badmcall2(SB) 188 189 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 190 // of the G stack. We need to distinguish the routine that 191 // lives at the bottom of the G stack from the one that lives 192 // at the top of the system stack because the one at the top of 193 // the system stack terminates the stack walk (see topofstack()). 194 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 195 // We have several undefs here so that 16 bytes past 196 // $runtime·systemstack_switch lies within them whether or not the 197 // instructions that derive r2 from r12 are there. 198 UNDEF 199 UNDEF 200 UNDEF 201 BL (LR) // make sure this function is not leaf 202 RET 203 204 // func systemstack(fn func()) 205 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 206 MOVD fn+0(FP), R3 // R3 = fn 207 MOVD R3, R11 // context 208 MOVD g_m(g), R4 // R4 = m 209 210 MOVD m_gsignal(R4), R5 // R5 = gsignal 211 CMP g, R5 212 BEQ noswitch 213 214 MOVD m_g0(R4), R5 // R5 = g0 215 CMP g, R5 216 BEQ noswitch 217 218 MOVD m_curg(R4), R6 219 CMP g, R6 220 BEQ switch 221 222 // Bad: g is not gsignal, not g0, not curg. What is it? 223 // Hide call from linker nosplit analysis. 224 MOVD $runtime·badsystemstack(SB), R12 225 MOVD R12, CTR 226 BL (CTR) 227 228 switch: 229 // save our state in g->sched. Pretend to 230 // be systemstack_switch if the G stack is scanned. 231 MOVD $runtime·systemstack_switch(SB), R6 232 ADD $16, R6 // get past prologue (including r2-setting instructions when they're there) 233 MOVD R6, (g_sched+gobuf_pc)(g) 234 MOVD R1, (g_sched+gobuf_sp)(g) 235 MOVD R0, (g_sched+gobuf_lr)(g) 236 MOVD g, (g_sched+gobuf_g)(g) 237 238 // switch to g0 239 MOVD R5, g 240 BL runtime·save_g(SB) 241 MOVD (g_sched+gobuf_sp)(g), R3 242 // make it look like mstart called systemstack on g0, to stop traceback 243 SUB $FIXED_FRAME, R3 244 MOVD $runtime·mstart(SB), R4 245 MOVD R4, 0(R3) 246 MOVD R3, R1 247 248 // call target function 249 MOVD 0(R11), R12 // code pointer 250 MOVD R12, CTR 251 BL (CTR) 252 253 // restore TOC pointer. It seems unlikely that we will use systemstack 254 // to call a function defined in another module, but the results of 255 // doing so would be so confusing that it's worth doing this. 256 MOVD g_m(g), R3 257 MOVD m_curg(R3), g 258 MOVD (g_sched+gobuf_sp)(g), R3 259 MOVD 24(R3), R2 260 // switch back to g 261 MOVD g_m(g), R3 262 MOVD m_curg(R3), g 263 BL runtime·save_g(SB) 264 MOVD (g_sched+gobuf_sp)(g), R1 265 MOVD R0, (g_sched+gobuf_sp)(g) 266 RET 267 268 noswitch: 269 // already on m stack, just call directly 270 MOVD 0(R11), R12 // code pointer 271 MOVD R12, CTR 272 BL (CTR) 273 MOVD 24(R1), R2 274 RET 275 276 /* 277 * support for morestack 278 */ 279 280 // Called during function prolog when more stack is needed. 281 // Caller has already loaded: 282 // R3: framesize, R4: argsize, R5: LR 283 // 284 // The traceback routines see morestack on a g0 as being 285 // the top of a stack (for example, morestack calling newstack 286 // calling the scheduler calling newm calling gc), so we must 287 // record an argument size. For that purpose, it has no arguments. 288 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 289 // Cannot grow scheduler stack (m->g0). 290 MOVD g_m(g), R7 291 MOVD m_g0(R7), R8 292 CMP g, R8 293 BNE 2(PC) 294 BL runtime·abort(SB) 295 296 // Cannot grow signal stack (m->gsignal). 297 MOVD m_gsignal(R7), R8 298 CMP g, R8 299 BNE 2(PC) 300 BL runtime·abort(SB) 301 302 // Called from f. 303 // Set g->sched to context in f. 304 MOVD R11, (g_sched+gobuf_ctxt)(g) 305 MOVD R1, (g_sched+gobuf_sp)(g) 306 MOVD LR, R8 307 MOVD R8, (g_sched+gobuf_pc)(g) 308 MOVD R5, (g_sched+gobuf_lr)(g) 309 310 // Called from f. 311 // Set m->morebuf to f's caller. 312 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 313 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 314 MOVD g, (m_morebuf+gobuf_g)(R7) 315 316 // Call newstack on m->g0's stack. 317 MOVD m_g0(R7), g 318 BL runtime·save_g(SB) 319 MOVD (g_sched+gobuf_sp)(g), R1 320 BL runtime·newstack(SB) 321 322 // Not reached, but make sure the return PC from the call to newstack 323 // is still in this function, and not the beginning of the next. 324 UNDEF 325 326 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 327 MOVD R0, R11 328 BR runtime·morestack(SB) 329 330 TEXT runtime·stackBarrier(SB),NOSPLIT,$0 331 // We came here via a RET to an overwritten LR. 332 // R3 may be live. Other registers are available. 333 334 // Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal. 335 MOVD (g_stkbar+slice_array)(g), R4 336 MOVD g_stkbarPos(g), R5 337 MOVD $stkbar__size, R6 338 MULLD R5, R6 339 ADD R4, R6 340 MOVD stkbar_savedLRVal(R6), R6 341 // Record that this stack barrier was hit. 342 ADD $1, R5 343 MOVD R5, g_stkbarPos(g) 344 // Jump to the original return PC. 345 MOVD R6, CTR 346 BR (CTR) 347 348 // reflectcall: call a function with the given argument list 349 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 350 // we don't have variable-sized frames, so we use a small number 351 // of constant-sized-frame functions to encode a few bits of size in the pc. 352 // Caution: ugly multiline assembly macros in your future! 353 354 #define DISPATCH(NAME,MAXSIZE) \ 355 MOVD $MAXSIZE, R31; \ 356 CMP R3, R31; \ 357 BGT 4(PC); \ 358 MOVD $NAME(SB), R12; \ 359 MOVD R12, CTR; \ 360 BR (CTR) 361 // Note: can't just "BR NAME(SB)" - bad inlining results. 362 363 TEXT reflect·call(SB), NOSPLIT, $0-0 364 BR ·reflectcall(SB) 365 366 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32 367 MOVWZ argsize+24(FP), R3 368 // NOTE(rsc): No call16, because CALLFN needs four words 369 // of argument space to invoke callwritebarrier. 370 DISPATCH(runtime·call32, 32) 371 DISPATCH(runtime·call64, 64) 372 DISPATCH(runtime·call128, 128) 373 DISPATCH(runtime·call256, 256) 374 DISPATCH(runtime·call512, 512) 375 DISPATCH(runtime·call1024, 1024) 376 DISPATCH(runtime·call2048, 2048) 377 DISPATCH(runtime·call4096, 4096) 378 DISPATCH(runtime·call8192, 8192) 379 DISPATCH(runtime·call16384, 16384) 380 DISPATCH(runtime·call32768, 32768) 381 DISPATCH(runtime·call65536, 65536) 382 DISPATCH(runtime·call131072, 131072) 383 DISPATCH(runtime·call262144, 262144) 384 DISPATCH(runtime·call524288, 524288) 385 DISPATCH(runtime·call1048576, 1048576) 386 DISPATCH(runtime·call2097152, 2097152) 387 DISPATCH(runtime·call4194304, 4194304) 388 DISPATCH(runtime·call8388608, 8388608) 389 DISPATCH(runtime·call16777216, 16777216) 390 DISPATCH(runtime·call33554432, 33554432) 391 DISPATCH(runtime·call67108864, 67108864) 392 DISPATCH(runtime·call134217728, 134217728) 393 DISPATCH(runtime·call268435456, 268435456) 394 DISPATCH(runtime·call536870912, 536870912) 395 DISPATCH(runtime·call1073741824, 1073741824) 396 MOVD $runtime·badreflectcall(SB), R12 397 MOVD R12, CTR 398 BR (CTR) 399 400 #define CALLFN(NAME,MAXSIZE) \ 401 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 402 NO_LOCAL_POINTERS; \ 403 /* copy arguments to stack */ \ 404 MOVD arg+16(FP), R3; \ 405 MOVWZ argsize+24(FP), R4; \ 406 MOVD R1, R5; \ 407 ADD $(FIXED_FRAME-1), R5; \ 408 SUB $1, R3; \ 409 ADD R5, R4; \ 410 CMP R5, R4; \ 411 BEQ 4(PC); \ 412 MOVBZU 1(R3), R6; \ 413 MOVBZU R6, 1(R5); \ 414 BR -4(PC); \ 415 /* call function */ \ 416 MOVD f+8(FP), R11; \ 417 MOVD (R11), R12; \ 418 MOVD R12, CTR; \ 419 PCDATA $PCDATA_StackMapIndex, $0; \ 420 BL (CTR); \ 421 MOVD 24(R1), R2; \ 422 /* copy return values back */ \ 423 MOVD arg+16(FP), R3; \ 424 MOVWZ n+24(FP), R4; \ 425 MOVWZ retoffset+28(FP), R6; \ 426 MOVD R1, R5; \ 427 ADD R6, R5; \ 428 ADD R6, R3; \ 429 SUB R6, R4; \ 430 ADD $(FIXED_FRAME-1), R5; \ 431 SUB $1, R3; \ 432 ADD R5, R4; \ 433 loop: \ 434 CMP R5, R4; \ 435 BEQ end; \ 436 MOVBZU 1(R5), R6; \ 437 MOVBZU R6, 1(R3); \ 438 BR loop; \ 439 end: \ 440 /* execute write barrier updates */ \ 441 MOVD argtype+0(FP), R7; \ 442 MOVD arg+16(FP), R3; \ 443 MOVWZ n+24(FP), R4; \ 444 MOVWZ retoffset+28(FP), R6; \ 445 MOVD R7, FIXED_FRAME+0(R1); \ 446 MOVD R3, FIXED_FRAME+8(R1); \ 447 MOVD R4, FIXED_FRAME+16(R1); \ 448 MOVD R6, FIXED_FRAME+24(R1); \ 449 BL runtime·callwritebarrier(SB); \ 450 RET 451 452 CALLFN(·call32, 32) 453 CALLFN(·call64, 64) 454 CALLFN(·call128, 128) 455 CALLFN(·call256, 256) 456 CALLFN(·call512, 512) 457 CALLFN(·call1024, 1024) 458 CALLFN(·call2048, 2048) 459 CALLFN(·call4096, 4096) 460 CALLFN(·call8192, 8192) 461 CALLFN(·call16384, 16384) 462 CALLFN(·call32768, 32768) 463 CALLFN(·call65536, 65536) 464 CALLFN(·call131072, 131072) 465 CALLFN(·call262144, 262144) 466 CALLFN(·call524288, 524288) 467 CALLFN(·call1048576, 1048576) 468 CALLFN(·call2097152, 2097152) 469 CALLFN(·call4194304, 4194304) 470 CALLFN(·call8388608, 8388608) 471 CALLFN(·call16777216, 16777216) 472 CALLFN(·call33554432, 33554432) 473 CALLFN(·call67108864, 67108864) 474 CALLFN(·call134217728, 134217728) 475 CALLFN(·call268435456, 268435456) 476 CALLFN(·call536870912, 536870912) 477 CALLFN(·call1073741824, 1073741824) 478 479 TEXT runtime·procyield(SB),NOSPLIT,$0-0 480 RET 481 482 // void jmpdefer(fv, sp); 483 // called from deferreturn. 484 // 1. grab stored LR for caller 485 // 2. sub 8 bytes to get back to either nop or toc reload before deferreturn 486 // 3. BR to fn 487 // When dynamically linking Go, it is not sufficient to rewind to the BL 488 // deferreturn -- we might be jumping between modules and so we need to reset 489 // the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* 490 // the BL deferreturn and jmpdefer rewinds to that. 491 TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 492 MOVD 0(R1), R31 493 SUB $8, R31 494 MOVD R31, LR 495 496 MOVD fv+0(FP), R11 497 MOVD argp+8(FP), R1 498 SUB $FIXED_FRAME, R1 499 MOVD 0(R11), R12 500 MOVD R12, CTR 501 BR (CTR) 502 503 // Save state of caller into g->sched. Smashes R31. 504 TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 505 MOVD LR, R31 506 MOVD R31, (g_sched+gobuf_pc)(g) 507 MOVD R1, (g_sched+gobuf_sp)(g) 508 MOVD R0, (g_sched+gobuf_lr)(g) 509 MOVD R0, (g_sched+gobuf_ret)(g) 510 MOVD R0, (g_sched+gobuf_ctxt)(g) 511 RET 512 513 // func asmcgocall(fn, arg unsafe.Pointer) int32 514 // Call fn(arg) on the scheduler stack, 515 // aligned appropriately for the gcc ABI. 516 // See cgocall.go for more details. 517 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 518 MOVD fn+0(FP), R3 519 MOVD arg+8(FP), R4 520 521 MOVD R1, R7 // save original stack pointer 522 MOVD g, R5 523 524 // Figure out if we need to switch to m->g0 stack. 525 // We get called to create new OS threads too, and those 526 // come in on the m->g0 stack already. 527 MOVD g_m(g), R6 528 MOVD m_g0(R6), R6 529 CMP R6, g 530 BEQ g0 531 BL gosave<>(SB) 532 MOVD R6, g 533 BL runtime·save_g(SB) 534 MOVD (g_sched+gobuf_sp)(g), R1 535 536 // Now on a scheduling stack (a pthread-created stack). 537 g0: 538 // Save room for two of our pointers, plus 32 bytes of callee 539 // save area that lives on the caller stack. 540 SUB $48, R1 541 RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI 542 MOVD R5, 40(R1) // save old g on stack 543 MOVD (g_stack+stack_hi)(R5), R5 544 SUB R7, R5 545 MOVD R5, 32(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 546 MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?) 547 // This is a "global call", so put the global entry point in r12 548 MOVD R3, R12 549 MOVD R12, CTR 550 MOVD R4, R3 // arg in r3 551 BL (CTR) 552 553 // C code can clobber R0, so set it back to 0. F27-F31 are 554 // callee save, so we don't need to recover those. 555 XOR R0, R0 556 // Restore g, stack pointer, toc pointer. 557 // R3 is errno, so don't touch it 558 MOVD 40(R1), g 559 MOVD (g_stack+stack_hi)(g), R5 560 MOVD 32(R1), R6 561 SUB R6, R5 562 MOVD 24(R5), R2 563 BL runtime·save_g(SB) 564 MOVD (g_stack+stack_hi)(g), R5 565 MOVD 32(R1), R6 566 SUB R6, R5 567 MOVD R5, R1 568 569 MOVW R3, ret+16(FP) 570 RET 571 572 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 573 // Turn the fn into a Go func (by taking its address) and call 574 // cgocallback_gofunc. 575 TEXT runtime·cgocallback(SB),NOSPLIT,$24-24 576 MOVD $fn+0(FP), R3 577 MOVD R3, FIXED_FRAME+0(R1) 578 MOVD frame+8(FP), R3 579 MOVD R3, FIXED_FRAME+8(R1) 580 MOVD framesize+16(FP), R3 581 MOVD R3, FIXED_FRAME+16(R1) 582 MOVD $runtime·cgocallback_gofunc(SB), R12 583 MOVD R12, CTR 584 BL (CTR) 585 RET 586 587 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize) 588 // See cgocall.go for more details. 589 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-24 590 NO_LOCAL_POINTERS 591 592 // Load m and g from thread-local storage. 593 MOVB runtime·iscgo(SB), R3 594 CMP R3, $0 595 BEQ nocgo 596 BL runtime·load_g(SB) 597 nocgo: 598 599 // If g is nil, Go did not create the current thread. 600 // Call needm to obtain one for temporary use. 601 // In this case, we're running on the thread stack, so there's 602 // lots of space, but the linker doesn't know. Hide the call from 603 // the linker analysis by using an indirect call. 604 CMP g, $0 605 BNE havem 606 MOVD g, savedm-8(SP) // g is zero, so is m. 607 MOVD $runtime·needm(SB), R12 608 MOVD R12, CTR 609 BL (CTR) 610 611 // Set m->sched.sp = SP, so that if a panic happens 612 // during the function we are about to execute, it will 613 // have a valid SP to run on the g0 stack. 614 // The next few lines (after the havem label) 615 // will save this SP onto the stack and then write 616 // the same SP back to m->sched.sp. That seems redundant, 617 // but if an unrecovered panic happens, unwindm will 618 // restore the g->sched.sp from the stack location 619 // and then systemstack will try to use it. If we don't set it here, 620 // that restored SP will be uninitialized (typically 0) and 621 // will not be usable. 622 MOVD g_m(g), R3 623 MOVD m_g0(R3), R3 624 MOVD R1, (g_sched+gobuf_sp)(R3) 625 626 havem: 627 MOVD g_m(g), R8 628 MOVD R8, savedm-8(SP) 629 // Now there's a valid m, and we're running on its m->g0. 630 // Save current m->g0->sched.sp on stack and then set it to SP. 631 // Save current sp in m->g0->sched.sp in preparation for 632 // switch back to m->curg stack. 633 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 634 MOVD m_g0(R8), R3 635 MOVD (g_sched+gobuf_sp)(R3), R4 636 MOVD R4, savedsp-16(SP) 637 MOVD R1, (g_sched+gobuf_sp)(R3) 638 639 // Switch to m->curg stack and call runtime.cgocallbackg. 640 // Because we are taking over the execution of m->curg 641 // but *not* resuming what had been running, we need to 642 // save that information (m->curg->sched) so we can restore it. 643 // We can restore m->curg->sched.sp easily, because calling 644 // runtime.cgocallbackg leaves SP unchanged upon return. 645 // To save m->curg->sched.pc, we push it onto the stack. 646 // This has the added benefit that it looks to the traceback 647 // routine like cgocallbackg is going to return to that 648 // PC (because the frame we allocate below has the same 649 // size as cgocallback_gofunc's frame declared above) 650 // so that the traceback will seamlessly trace back into 651 // the earlier calls. 652 // 653 // In the new goroutine, -16(SP) and -8(SP) are unused. 654 MOVD m_curg(R8), g 655 BL runtime·save_g(SB) 656 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 657 MOVD (g_sched+gobuf_pc)(g), R5 658 MOVD R5, -(FIXED_FRAME+16)(R4) 659 MOVD $-(FIXED_FRAME+16)(R4), R1 660 BL runtime·cgocallbackg(SB) 661 662 // Restore g->sched (== m->curg->sched) from saved values. 663 MOVD 0(R1), R5 664 MOVD R5, (g_sched+gobuf_pc)(g) 665 MOVD $(FIXED_FRAME+16)(R1), R4 666 MOVD R4, (g_sched+gobuf_sp)(g) 667 668 // Switch back to m->g0's stack and restore m->g0->sched.sp. 669 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 670 // so we do not have to restore it.) 671 MOVD g_m(g), R8 672 MOVD m_g0(R8), g 673 BL runtime·save_g(SB) 674 MOVD (g_sched+gobuf_sp)(g), R1 675 MOVD savedsp-16(SP), R4 676 MOVD R4, (g_sched+gobuf_sp)(g) 677 678 // If the m on entry was nil, we called needm above to borrow an m 679 // for the duration of the call. Since the call is over, return it with dropm. 680 MOVD savedm-8(SP), R6 681 CMP R6, $0 682 BNE droppedm 683 MOVD $runtime·dropm(SB), R12 684 MOVD R12, CTR 685 BL (CTR) 686 droppedm: 687 688 // Done! 689 RET 690 691 // void setg(G*); set g. for use by needm. 692 TEXT runtime·setg(SB), NOSPLIT, $0-8 693 MOVD gg+0(FP), g 694 // This only happens if iscgo, so jump straight to save_g 695 BL runtime·save_g(SB) 696 RET 697 698 // void setg_gcc(G*); set g in C TLS. 699 // Must obey the gcc calling convention. 700 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 701 // The standard prologue clobbers R31, which is callee-save in 702 // the C ABI, so we have to use $-8-0 and save LR ourselves. 703 MOVD LR, R4 704 // Also save g and R31, since they're callee-save in C ABI 705 MOVD R31, R5 706 MOVD g, R6 707 708 MOVD R3, g 709 BL runtime·save_g(SB) 710 711 MOVD R6, g 712 MOVD R5, R31 713 MOVD R4, LR 714 RET 715 716 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 717 MOVD FIXED_FRAME+8(R1), R3 // LR saved by caller 718 MOVD runtime·stackBarrierPC(SB), R4 719 CMP R3, R4 720 BNE nobar 721 // Get original return PC. 722 BL runtime·nextBarrierPC(SB) 723 MOVD FIXED_FRAME+0(R1), R3 724 nobar: 725 MOVD R3, ret+8(FP) 726 RET 727 728 TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16 729 MOVD pc+8(FP), R3 730 MOVD FIXED_FRAME+8(R1), R4 731 MOVD runtime·stackBarrierPC(SB), R5 732 CMP R4, R5 733 BEQ setbar 734 MOVD R3, FIXED_FRAME+8(R1) // set LR in caller 735 RET 736 setbar: 737 // Set the stack barrier return PC. 738 MOVD R3, FIXED_FRAME+0(R1) 739 BL runtime·setNextBarrierPC(SB) 740 RET 741 742 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 743 MOVD argp+0(FP), R3 744 SUB $FIXED_FRAME, R3 745 MOVD R3, ret+8(FP) 746 RET 747 748 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 749 MOVW (R0), R0 750 UNDEF 751 752 #define TBRL 268 753 #define TBRU 269 /* Time base Upper/Lower */ 754 755 // int64 runtime·cputicks(void) 756 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 757 MOVW SPR(TBRU), R4 758 MOVW SPR(TBRL), R3 759 MOVW SPR(TBRU), R5 760 CMPW R4, R5 761 BNE -4(PC) 762 SLD $32, R5 763 OR R5, R3 764 MOVD R3, ret+0(FP) 765 RET 766 767 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 768 // redirects to memhash(p, h, size) using the size 769 // stored in the closure. 770 TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24 771 GO_ARGS 772 NO_LOCAL_POINTERS 773 MOVD p+0(FP), R3 774 MOVD h+8(FP), R4 775 MOVD 8(R11), R5 776 MOVD R3, FIXED_FRAME+0(R1) 777 MOVD R4, FIXED_FRAME+8(R1) 778 MOVD R5, FIXED_FRAME+16(R1) 779 BL runtime·memhash(SB) 780 MOVD FIXED_FRAME+24(R1), R3 781 MOVD R3, ret+16(FP) 782 RET 783 784 // AES hashing not implemented for ppc64 785 TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0 786 MOVW (R0), R1 787 TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0 788 MOVW (R0), R1 789 TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0 790 MOVW (R0), R1 791 TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0 792 MOVW (R0), R1 793 794 TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25 795 MOVD a+0(FP), R3 796 MOVD b+8(FP), R4 797 MOVD size+16(FP), R5 798 SUB $1, R3 799 SUB $1, R4 800 ADD R3, R5, R8 801 loop: 802 CMP R3, R8 803 BNE test 804 MOVD $1, R3 805 MOVB R3, ret+24(FP) 806 RET 807 test: 808 MOVBZU 1(R3), R6 809 MOVBZU 1(R4), R7 810 CMP R6, R7 811 BEQ loop 812 813 MOVB R0, ret+24(FP) 814 RET 815 816 // memequal_varlen(a, b unsafe.Pointer) bool 817 TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 818 MOVD a+0(FP), R3 819 MOVD b+8(FP), R4 820 CMP R3, R4 821 BEQ eq 822 MOVD 8(R11), R5 // compiler stores size at offset 8 in the closure 823 MOVD R3, FIXED_FRAME+0(R1) 824 MOVD R4, FIXED_FRAME+8(R1) 825 MOVD R5, FIXED_FRAME+16(R1) 826 BL runtime·memeq(SB) 827 MOVBZ FIXED_FRAME+24(R1), R3 828 MOVB R3, ret+16(FP) 829 RET 830 eq: 831 MOVD $1, R3 832 MOVB R3, ret+16(FP) 833 RET 834 835 // eqstring tests whether two strings are equal. 836 // The compiler guarantees that strings passed 837 // to eqstring have equal length. 838 // See runtime_test.go:eqstring_generic for 839 // equivalent Go code. 840 TEXT runtime·eqstring(SB),NOSPLIT,$0-33 841 MOVD s1str+0(FP), R3 842 MOVD s2str+16(FP), R4 843 MOVD $1, R5 844 MOVB R5, ret+32(FP) 845 CMP R3, R4 846 BNE 2(PC) 847 RET 848 MOVD s1len+8(FP), R5 849 SUB $1, R3 850 SUB $1, R4 851 ADD R3, R5, R8 852 loop: 853 CMP R3, R8 854 BNE 2(PC) 855 RET 856 MOVBZU 1(R3), R6 857 MOVBZU 1(R4), R7 858 CMP R6, R7 859 BEQ loop 860 MOVB R0, ret+32(FP) 861 RET 862 863 // TODO: share code with memeq? 864 TEXT bytes·Equal(SB),NOSPLIT,$0-49 865 MOVD a_len+8(FP), R3 866 MOVD b_len+32(FP), R4 867 868 CMP R3, R4 // unequal lengths are not equal 869 BNE noteq 870 871 MOVD a+0(FP), R5 872 MOVD b+24(FP), R6 873 SUB $1, R5 874 SUB $1, R6 875 ADD R5, R3 // end-1 876 877 loop: 878 CMP R5, R3 879 BEQ equal // reached the end 880 MOVBZU 1(R5), R4 881 MOVBZU 1(R6), R7 882 CMP R4, R7 883 BEQ loop 884 885 noteq: 886 MOVBZ R0, ret+48(FP) 887 RET 888 889 equal: 890 MOVD $1, R3 891 MOVBZ R3, ret+48(FP) 892 RET 893 894 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 895 MOVD s+0(FP), R3 896 MOVD s_len+8(FP), R4 897 MOVBZ c+24(FP), R5 // byte to find 898 MOVD R3, R6 // store base for later 899 SUB $1, R3 900 ADD R3, R4 // end-1 901 902 loop: 903 CMP R3, R4 904 BEQ notfound 905 MOVBZU 1(R3), R7 906 CMP R7, R5 907 BNE loop 908 909 SUB R6, R3 // remove base 910 MOVD R3, ret+32(FP) 911 RET 912 913 notfound: 914 MOVD $-1, R3 915 MOVD R3, ret+32(FP) 916 RET 917 918 TEXT strings·IndexByte(SB),NOSPLIT,$0-32 919 MOVD p+0(FP), R3 920 MOVD b_len+8(FP), R4 921 MOVBZ c+16(FP), R5 // byte to find 922 MOVD R3, R6 // store base for later 923 SUB $1, R3 924 ADD R3, R4 // end-1 925 926 loop: 927 CMP R3, R4 928 BEQ notfound 929 MOVBZU 1(R3), R7 930 CMP R7, R5 931 BNE loop 932 933 SUB R6, R3 // remove base 934 MOVD R3, ret+24(FP) 935 RET 936 937 notfound: 938 MOVD $-1, R3 939 MOVD R3, ret+24(FP) 940 RET 941 942 TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 943 MOVD s1_base+0(FP), R5 944 MOVD s1_len+8(FP), R3 945 MOVD s2_base+16(FP), R6 946 MOVD s2_len+24(FP), R4 947 MOVD $ret+32(FP), R7 948 BR runtime·cmpbody<>(SB) 949 950 TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56 951 MOVD s1+0(FP), R5 952 MOVD s1+8(FP), R3 953 MOVD s2+24(FP), R6 954 MOVD s2+32(FP), R4 955 MOVD $ret+48(FP), R7 956 BR runtime·cmpbody<>(SB) 957 958 // On entry: 959 // R3 is the length of s1 960 // R4 is the length of s2 961 // R5 points to the start of s1 962 // R6 points to the start of s2 963 // R7 points to return value (-1/0/1 will be written here) 964 // 965 // On exit: 966 // R5, R6, R8, R9 and R10 are clobbered 967 TEXT runtime·cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0 968 CMP R5, R6 969 BEQ samebytes // same starting pointers; compare lengths 970 SUB $1, R5 971 SUB $1, R6 972 MOVD R4, R8 973 CMP R3, R4 974 BGE 2(PC) 975 MOVD R3, R8 // R8 is min(R3, R4) 976 ADD R5, R8 // R5 is current byte in s1, R8 is last byte in s1 to compare 977 loop: 978 CMP R5, R8 979 BEQ samebytes // all compared bytes were the same; compare lengths 980 MOVBZU 1(R5), R9 981 MOVBZU 1(R6), R10 982 CMP R9, R10 983 BEQ loop 984 // bytes differed 985 MOVD $1, R4 986 BGT 2(PC) 987 NEG R4 988 MOVD R4, (R7) 989 RET 990 samebytes: 991 MOVD $1, R8 992 CMP R3, R4 993 BNE 3(PC) 994 MOVD R0, (R7) 995 RET 996 BGT 2(PC) 997 NEG R8 998 MOVD R8, (R7) 999 RET 1000 1001 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 1002 MOVD g_m(g), R4 1003 MOVWZ m_fastrand(R4), R3 1004 ADD R3, R3 1005 CMPW R3, $0 1006 BGE 2(PC) 1007 XOR $0x88888eef, R3 1008 MOVW R3, m_fastrand(R4) 1009 MOVW R3, ret+0(FP) 1010 RET 1011 1012 TEXT runtime·return0(SB), NOSPLIT, $0 1013 MOVW $0, R3 1014 RET 1015 1016 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 1017 // Must obey the gcc calling convention. 1018 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 1019 // g (R30) and R31 are callee-save in the C ABI, so save them 1020 MOVD g, R4 1021 MOVD R31, R5 1022 MOVD LR, R6 1023 1024 BL runtime·load_g(SB) // clobbers g (R30), R31 1025 MOVD g_m(g), R3 1026 MOVD m_curg(R3), R3 1027 MOVD (g_stack+stack_hi)(R3), R3 1028 1029 MOVD R4, g 1030 MOVD R5, R31 1031 MOVD R6, LR 1032 RET 1033 1034 // The top-most function running on a goroutine 1035 // returns to goexit+PCQuantum. 1036 // 1037 // When dynamically linking Go, it can be returned to from a function 1038 // implemented in a different module and so needs to reload the TOC pointer 1039 // from the stack (although this function declares that it does not set up x-a 1040 // frame, newproc1 does in fact allocate one for goexit and saves the TOC 1041 // pointer in the correct place). 1042 // goexit+_PCQuantum is halfway through the usual global entry point prologue 1043 // that derives r2 from r12 which is a bit silly, but not harmful. 1044 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0 1045 MOVD 24(R1), R2 1046 BL runtime·goexit1(SB) // does not return 1047 // traceback from goexit1 must hit code range of goexit 1048 MOVD R0, R0 // NOP 1049 1050 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 1051 RET 1052 1053 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8 1054 RET 1055 1056 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8 1057 RET 1058 1059 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8 1060 RET 1061 1062 TEXT runtime·sigreturn(SB),NOSPLIT,$0-8 1063 RET 1064 1065 // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the 1066 // module containing runtime) to the frame that goexit will execute in when 1067 // the goroutine exits. It's implemented in assembly mainly because that's the 1068 // easiest way to get access to R2. 1069 TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8 1070 MOVD sp+0(FP), R3 1071 MOVD R2, 24(R3) 1072 RET 1073 1074 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 1075 ADD $-8, R1 1076 MOVD R31, 0(R1) 1077 MOVD runtime·lastmoduledatap(SB), R4 1078 MOVD R3, moduledata_next(R4) 1079 MOVD R3, runtime·lastmoduledatap(SB) 1080 MOVD 0(R1), R31 1081 ADD $8, R1 1082 RET 1083 1084 TEXT ·checkASM(SB),NOSPLIT,$0-1 1085 MOVW $1, R3 1086 MOVB R3, ret+0(FP) 1087 RET