github.com/aloncn/graphics-go@v0.0.1/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 BEQ needm 606 607 MOVD g_m(g), R8 608 MOVD R8, savedm-8(SP) 609 BR havem 610 611 needm: 612 MOVD g, savedm-8(SP) // g is zero, so is m. 613 MOVD $runtime·needm(SB), R12 614 MOVD R12, CTR 615 BL (CTR) 616 617 // Set m->sched.sp = SP, so that if a panic happens 618 // during the function we are about to execute, it will 619 // have a valid SP to run on the g0 stack. 620 // The next few lines (after the havem label) 621 // will save this SP onto the stack and then write 622 // the same SP back to m->sched.sp. That seems redundant, 623 // but if an unrecovered panic happens, unwindm will 624 // restore the g->sched.sp from the stack location 625 // and then systemstack will try to use it. If we don't set it here, 626 // that restored SP will be uninitialized (typically 0) and 627 // will not be usable. 628 MOVD g_m(g), R8 629 MOVD m_g0(R8), R3 630 MOVD R1, (g_sched+gobuf_sp)(R3) 631 632 havem: 633 // Now there's a valid m, and we're running on its m->g0. 634 // Save current m->g0->sched.sp on stack and then set it to SP. 635 // Save current sp in m->g0->sched.sp in preparation for 636 // switch back to m->curg stack. 637 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 638 MOVD m_g0(R8), R3 639 MOVD (g_sched+gobuf_sp)(R3), R4 640 MOVD R4, savedsp-16(SP) 641 MOVD R1, (g_sched+gobuf_sp)(R3) 642 643 // Switch to m->curg stack and call runtime.cgocallbackg. 644 // Because we are taking over the execution of m->curg 645 // but *not* resuming what had been running, we need to 646 // save that information (m->curg->sched) so we can restore it. 647 // We can restore m->curg->sched.sp easily, because calling 648 // runtime.cgocallbackg leaves SP unchanged upon return. 649 // To save m->curg->sched.pc, we push it onto the stack. 650 // This has the added benefit that it looks to the traceback 651 // routine like cgocallbackg is going to return to that 652 // PC (because the frame we allocate below has the same 653 // size as cgocallback_gofunc's frame declared above) 654 // so that the traceback will seamlessly trace back into 655 // the earlier calls. 656 // 657 // In the new goroutine, -16(SP) and -8(SP) are unused. 658 MOVD m_curg(R8), g 659 BL runtime·save_g(SB) 660 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 661 MOVD (g_sched+gobuf_pc)(g), R5 662 MOVD R5, -(FIXED_FRAME+16)(R4) 663 MOVD $-(FIXED_FRAME+16)(R4), R1 664 BL runtime·cgocallbackg(SB) 665 666 // Restore g->sched (== m->curg->sched) from saved values. 667 MOVD 0(R1), R5 668 MOVD R5, (g_sched+gobuf_pc)(g) 669 MOVD $(FIXED_FRAME+16)(R1), R4 670 MOVD R4, (g_sched+gobuf_sp)(g) 671 672 // Switch back to m->g0's stack and restore m->g0->sched.sp. 673 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 674 // so we do not have to restore it.) 675 MOVD g_m(g), R8 676 MOVD m_g0(R8), g 677 BL runtime·save_g(SB) 678 MOVD (g_sched+gobuf_sp)(g), R1 679 MOVD savedsp-16(SP), R4 680 MOVD R4, (g_sched+gobuf_sp)(g) 681 682 // If the m on entry was nil, we called needm above to borrow an m 683 // for the duration of the call. Since the call is over, return it with dropm. 684 MOVD savedm-8(SP), R6 685 CMP R6, $0 686 BNE droppedm 687 MOVD $runtime·dropm(SB), R12 688 MOVD R12, CTR 689 BL (CTR) 690 droppedm: 691 692 // Done! 693 RET 694 695 // void setg(G*); set g. for use by needm. 696 TEXT runtime·setg(SB), NOSPLIT, $0-8 697 MOVD gg+0(FP), g 698 // This only happens if iscgo, so jump straight to save_g 699 BL runtime·save_g(SB) 700 RET 701 702 // void setg_gcc(G*); set g in C TLS. 703 // Must obey the gcc calling convention. 704 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 705 // The standard prologue clobbers R31, which is callee-save in 706 // the C ABI, so we have to use $-8-0 and save LR ourselves. 707 MOVD LR, R4 708 // Also save g and R31, since they're callee-save in C ABI 709 MOVD R31, R5 710 MOVD g, R6 711 712 MOVD R3, g 713 BL runtime·save_g(SB) 714 715 MOVD R6, g 716 MOVD R5, R31 717 MOVD R4, LR 718 RET 719 720 TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 721 MOVD FIXED_FRAME+8(R1), R3 // LR saved by caller 722 MOVD runtime·stackBarrierPC(SB), R4 723 CMP R3, R4 724 BNE nobar 725 // Get original return PC. 726 BL runtime·nextBarrierPC(SB) 727 MOVD FIXED_FRAME+0(R1), R3 728 nobar: 729 MOVD R3, ret+8(FP) 730 RET 731 732 TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16 733 MOVD pc+8(FP), R3 734 MOVD FIXED_FRAME+8(R1), R4 735 MOVD runtime·stackBarrierPC(SB), R5 736 CMP R4, R5 737 BEQ setbar 738 MOVD R3, FIXED_FRAME+8(R1) // set LR in caller 739 RET 740 setbar: 741 // Set the stack barrier return PC. 742 MOVD R3, FIXED_FRAME+0(R1) 743 BL runtime·setNextBarrierPC(SB) 744 RET 745 746 TEXT runtime·getcallersp(SB),NOSPLIT,$0-16 747 MOVD argp+0(FP), R3 748 SUB $FIXED_FRAME, R3 749 MOVD R3, ret+8(FP) 750 RET 751 752 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 753 MOVW (R0), R0 754 UNDEF 755 756 #define TBRL 268 757 #define TBRU 269 /* Time base Upper/Lower */ 758 759 // int64 runtime·cputicks(void) 760 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 761 MOVW SPR(TBRU), R4 762 MOVW SPR(TBRL), R3 763 MOVW SPR(TBRU), R5 764 CMPW R4, R5 765 BNE -4(PC) 766 SLD $32, R5 767 OR R5, R3 768 MOVD R3, ret+0(FP) 769 RET 770 771 // memhash_varlen(p unsafe.Pointer, h seed) uintptr 772 // redirects to memhash(p, h, size) using the size 773 // stored in the closure. 774 TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24 775 GO_ARGS 776 NO_LOCAL_POINTERS 777 MOVD p+0(FP), R3 778 MOVD h+8(FP), R4 779 MOVD 8(R11), R5 780 MOVD R3, FIXED_FRAME+0(R1) 781 MOVD R4, FIXED_FRAME+8(R1) 782 MOVD R5, FIXED_FRAME+16(R1) 783 BL runtime·memhash(SB) 784 MOVD FIXED_FRAME+24(R1), R3 785 MOVD R3, ret+16(FP) 786 RET 787 788 // AES hashing not implemented for ppc64 789 TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0 790 MOVW (R0), R1 791 TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0 792 MOVW (R0), R1 793 TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0 794 MOVW (R0), R1 795 TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0 796 MOVW (R0), R1 797 798 TEXT runtime·memeq(SB),NOSPLIT|NOFRAME,$0-25 799 MOVD a+0(FP), R3 800 MOVD b+8(FP), R4 801 MOVD size+16(FP), R5 802 SUB $1, R3 803 SUB $1, R4 804 ADD R3, R5, R8 805 loop: 806 CMP R3, R8 807 BNE test 808 MOVD $1, R3 809 MOVB R3, ret+24(FP) 810 RET 811 test: 812 MOVBZU 1(R3), R6 813 MOVBZU 1(R4), R7 814 CMP R6, R7 815 BEQ loop 816 817 MOVB R0, ret+24(FP) 818 RET 819 820 // memequal_varlen(a, b unsafe.Pointer) bool 821 TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 822 MOVD a+0(FP), R3 823 MOVD b+8(FP), R4 824 CMP R3, R4 825 BEQ eq 826 MOVD 8(R11), R5 // compiler stores size at offset 8 in the closure 827 MOVD R3, FIXED_FRAME+0(R1) 828 MOVD R4, FIXED_FRAME+8(R1) 829 MOVD R5, FIXED_FRAME+16(R1) 830 BL runtime·memeq(SB) 831 MOVBZ FIXED_FRAME+24(R1), R3 832 MOVB R3, ret+16(FP) 833 RET 834 eq: 835 MOVD $1, R3 836 MOVB R3, ret+16(FP) 837 RET 838 839 // eqstring tests whether two strings are equal. 840 // The compiler guarantees that strings passed 841 // to eqstring have equal length. 842 // See runtime_test.go:eqstring_generic for 843 // equivalent Go code. 844 TEXT runtime·eqstring(SB),NOSPLIT,$0-33 845 MOVD s1str+0(FP), R3 846 MOVD s2str+16(FP), R4 847 MOVD $1, R5 848 MOVB R5, ret+32(FP) 849 CMP R3, R4 850 BNE 2(PC) 851 RET 852 MOVD s1len+8(FP), R5 853 SUB $1, R3 854 SUB $1, R4 855 ADD R3, R5, R8 856 loop: 857 CMP R3, R8 858 BNE 2(PC) 859 RET 860 MOVBZU 1(R3), R6 861 MOVBZU 1(R4), R7 862 CMP R6, R7 863 BEQ loop 864 MOVB R0, ret+32(FP) 865 RET 866 867 // TODO: share code with memeq? 868 TEXT bytes·Equal(SB),NOSPLIT,$0-49 869 MOVD a_len+8(FP), R3 870 MOVD b_len+32(FP), R4 871 872 CMP R3, R4 // unequal lengths are not equal 873 BNE noteq 874 875 MOVD a+0(FP), R5 876 MOVD b+24(FP), R6 877 SUB $1, R5 878 SUB $1, R6 879 ADD R5, R3 // end-1 880 881 loop: 882 CMP R5, R3 883 BEQ equal // reached the end 884 MOVBZU 1(R5), R4 885 MOVBZU 1(R6), R7 886 CMP R4, R7 887 BEQ loop 888 889 noteq: 890 MOVBZ R0, ret+48(FP) 891 RET 892 893 equal: 894 MOVD $1, R3 895 MOVBZ R3, ret+48(FP) 896 RET 897 898 TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 899 MOVD s+0(FP), R3 900 MOVD s_len+8(FP), R4 901 MOVBZ c+24(FP), R5 // byte to find 902 MOVD R3, R6 // store base for later 903 SUB $1, R3 904 ADD R3, R4 // end-1 905 906 loop: 907 CMP R3, R4 908 BEQ notfound 909 MOVBZU 1(R3), R7 910 CMP R7, R5 911 BNE loop 912 913 SUB R6, R3 // remove base 914 MOVD R3, ret+32(FP) 915 RET 916 917 notfound: 918 MOVD $-1, R3 919 MOVD R3, ret+32(FP) 920 RET 921 922 TEXT strings·IndexByte(SB),NOSPLIT,$0-32 923 MOVD p+0(FP), R3 924 MOVD b_len+8(FP), R4 925 MOVBZ c+16(FP), R5 // byte to find 926 MOVD R3, R6 // store base for later 927 SUB $1, R3 928 ADD R3, R4 // end-1 929 930 loop: 931 CMP R3, R4 932 BEQ notfound 933 MOVBZU 1(R3), R7 934 CMP R7, R5 935 BNE loop 936 937 SUB R6, R3 // remove base 938 MOVD R3, ret+24(FP) 939 RET 940 941 notfound: 942 MOVD $-1, R3 943 MOVD R3, ret+24(FP) 944 RET 945 946 TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 947 MOVD s1_base+0(FP), R5 948 MOVD s1_len+8(FP), R3 949 MOVD s2_base+16(FP), R6 950 MOVD s2_len+24(FP), R4 951 MOVD $ret+32(FP), R7 952 BR runtime·cmpbody<>(SB) 953 954 TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56 955 MOVD s1+0(FP), R5 956 MOVD s1+8(FP), R3 957 MOVD s2+24(FP), R6 958 MOVD s2+32(FP), R4 959 MOVD $ret+48(FP), R7 960 BR runtime·cmpbody<>(SB) 961 962 // On entry: 963 // R3 is the length of s1 964 // R4 is the length of s2 965 // R5 points to the start of s1 966 // R6 points to the start of s2 967 // R7 points to return value (-1/0/1 will be written here) 968 // 969 // On exit: 970 // R5, R6, R8, R9 and R10 are clobbered 971 TEXT runtime·cmpbody<>(SB),NOSPLIT|NOFRAME,$0-0 972 CMP R5, R6 973 BEQ samebytes // same starting pointers; compare lengths 974 SUB $1, R5 975 SUB $1, R6 976 MOVD R4, R8 977 CMP R3, R4 978 BGE 2(PC) 979 MOVD R3, R8 // R8 is min(R3, R4) 980 ADD R5, R8 // R5 is current byte in s1, R8 is last byte in s1 to compare 981 loop: 982 CMP R5, R8 983 BEQ samebytes // all compared bytes were the same; compare lengths 984 MOVBZU 1(R5), R9 985 MOVBZU 1(R6), R10 986 CMP R9, R10 987 BEQ loop 988 // bytes differed 989 MOVD $1, R4 990 BGT 2(PC) 991 NEG R4 992 MOVD R4, (R7) 993 RET 994 samebytes: 995 MOVD $1, R8 996 CMP R3, R4 997 BNE 3(PC) 998 MOVD R0, (R7) 999 RET 1000 BGT 2(PC) 1001 NEG R8 1002 MOVD R8, (R7) 1003 RET 1004 1005 TEXT runtime·fastrand1(SB), NOSPLIT, $0-4 1006 MOVD g_m(g), R4 1007 MOVWZ m_fastrand(R4), R3 1008 ADD R3, R3 1009 CMPW R3, $0 1010 BGE 2(PC) 1011 XOR $0x88888eef, R3 1012 MOVW R3, m_fastrand(R4) 1013 MOVW R3, ret+0(FP) 1014 RET 1015 1016 TEXT runtime·return0(SB), NOSPLIT, $0 1017 MOVW $0, R3 1018 RET 1019 1020 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 1021 // Must obey the gcc calling convention. 1022 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 1023 // g (R30) and R31 are callee-save in the C ABI, so save them 1024 MOVD g, R4 1025 MOVD R31, R5 1026 MOVD LR, R6 1027 1028 BL runtime·load_g(SB) // clobbers g (R30), R31 1029 MOVD g_m(g), R3 1030 MOVD m_curg(R3), R3 1031 MOVD (g_stack+stack_hi)(R3), R3 1032 1033 MOVD R4, g 1034 MOVD R5, R31 1035 MOVD R6, LR 1036 RET 1037 1038 // The top-most function running on a goroutine 1039 // returns to goexit+PCQuantum. 1040 // 1041 // When dynamically linking Go, it can be returned to from a function 1042 // implemented in a different module and so needs to reload the TOC pointer 1043 // from the stack (although this function declares that it does not set up x-a 1044 // frame, newproc1 does in fact allocate one for goexit and saves the TOC 1045 // pointer in the correct place). 1046 // goexit+_PCQuantum is halfway through the usual global entry point prologue 1047 // that derives r2 from r12 which is a bit silly, but not harmful. 1048 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0 1049 MOVD 24(R1), R2 1050 BL runtime·goexit1(SB) // does not return 1051 // traceback from goexit1 must hit code range of goexit 1052 MOVD R0, R0 // NOP 1053 1054 TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 1055 RET 1056 1057 TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8 1058 RET 1059 1060 TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8 1061 RET 1062 1063 TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8 1064 RET 1065 1066 TEXT runtime·sigreturn(SB),NOSPLIT,$0-8 1067 RET 1068 1069 // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the 1070 // module containing runtime) to the frame that goexit will execute in when 1071 // the goroutine exits. It's implemented in assembly mainly because that's the 1072 // easiest way to get access to R2. 1073 TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8 1074 MOVD sp+0(FP), R3 1075 MOVD R2, 24(R3) 1076 RET 1077 1078 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 1079 ADD $-8, R1 1080 MOVD R31, 0(R1) 1081 MOVD runtime·lastmoduledatap(SB), R4 1082 MOVD R3, moduledata_next(R4) 1083 MOVD R3, runtime·lastmoduledatap(SB) 1084 MOVD 0(R1), R31 1085 ADD $8, R1 1086 RET 1087 1088 TEXT ·checkASM(SB),NOSPLIT,$0-1 1089 MOVW $1, R3 1090 MOVB R3, ret+0(FP) 1091 RET