github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 BL runtime·save_g(SB) 28 MOVD $(-64*1024), R31 29 ADD R31, R1, R3 30 MOVD R3, g_stackguard0(g) 31 MOVD R3, g_stackguard1(g) 32 MOVD R3, (g_stack+stack_lo)(g) 33 MOVD R1, (g_stack+stack_hi)(g) 34 35 // if there is a _cgo_init, call it using the gcc ABI. 36 MOVD _cgo_init(SB), R12 37 CMP R0, R12 38 BEQ nocgo 39 #ifdef GOARCH_ppc64 40 // ppc64 use elf ABI v1. we must get the real entry address from 41 // first slot of the function descriptor before call. 42 MOVD 8(R12), R2 43 MOVD (R12), R12 44 #endif 45 MOVD R12, CTR // r12 = "global function entry point" 46 MOVD R13, R5 // arg 2: TLS base pointer 47 MOVD $setg_gcc<>(SB), R4 // arg 1: setg 48 MOVD g, R3 // arg 0: G 49 // C functions expect 32 bytes of space on caller stack frame 50 // and a 16-byte aligned R1 51 MOVD R1, R14 // save current stack 52 SUB $32, R1 // reserve 32 bytes 53 RLDCR $0, R1, $~15, R1 // 16-byte align 54 BL (CTR) // may clobber R0, R3-R12 55 MOVD R14, R1 // restore stack 56 MOVD 24(R1), R2 57 XOR R0, R0 // fix R0 58 59 nocgo: 60 // update stackguard after _cgo_init 61 MOVD (g_stack+stack_lo)(g), R3 62 ADD $const__StackGuard, R3 63 MOVD R3, g_stackguard0(g) 64 MOVD R3, g_stackguard1(g) 65 66 // set the per-goroutine and per-mach "registers" 67 MOVD $runtime·m0(SB), R3 68 69 // save m->g0 = g0 70 MOVD g, m_g0(R3) 71 // save m0 to g0->m 72 MOVD R3, g_m(g) 73 74 BL runtime·check(SB) 75 76 // args are already prepared 77 BL runtime·args(SB) 78 BL runtime·osinit(SB) 79 BL runtime·schedinit(SB) 80 81 // create a new goroutine to start program 82 MOVD $runtime·mainPC(SB), R3 // entry 83 MOVDU R3, -8(R1) 84 MOVDU R0, -8(R1) 85 MOVDU R0, -8(R1) 86 MOVDU R0, -8(R1) 87 MOVDU R0, -8(R1) 88 MOVDU R0, -8(R1) 89 BL runtime·newproc(SB) 90 ADD $(16+FIXED_FRAME), R1 91 92 // start this M 93 BL runtime·mstart(SB) 94 95 MOVD R0, 0(R0) 96 RET 97 98 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 99 GLOBL runtime·mainPC(SB),RODATA,$8 100 101 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 102 MOVD R0, 0(R0) // TODO: TD 103 RET 104 105 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 106 RET 107 108 TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0 109 // crosscall_ppc64 and crosscall2 need to reginit, but can't 110 // get at the 'runtime.reginit' symbol. 111 BR runtime·reginit(SB) 112 113 TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0 114 // set R0 to zero, it's expected by the toolchain 115 XOR R0, R0 116 RET 117 118 /* 119 * go-routine 120 */ 121 122 // void gosave(Gobuf*) 123 // save state in Gobuf; setjmp 124 TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8 125 MOVD buf+0(FP), R3 126 MOVD R1, gobuf_sp(R3) 127 MOVD LR, R31 128 MOVD R31, gobuf_pc(R3) 129 MOVD g, gobuf_g(R3) 130 MOVD R0, gobuf_lr(R3) 131 MOVD R0, gobuf_ret(R3) 132 // Assert ctxt is zero. See func save. 133 MOVD gobuf_ctxt(R3), R3 134 CMP R0, R3 135 BEQ 2(PC) 136 BL runtime·badctxt(SB) 137 RET 138 139 // void gogo(Gobuf*) 140 // restore state from Gobuf; longjmp 141 TEXT runtime·gogo(SB), NOSPLIT, $16-8 142 MOVD buf+0(FP), R5 143 MOVD gobuf_g(R5), g // make sure g is not nil 144 BL runtime·save_g(SB) 145 146 MOVD 0(g), R4 147 MOVD gobuf_sp(R5), R1 148 MOVD gobuf_lr(R5), R31 149 #ifndef GOOS_aix 150 MOVD 24(R1), R2 // restore R2 151 #endif 152 MOVD R31, LR 153 MOVD gobuf_ret(R5), R3 154 MOVD gobuf_ctxt(R5), R11 155 MOVD R0, gobuf_sp(R5) 156 MOVD R0, gobuf_ret(R5) 157 MOVD R0, gobuf_lr(R5) 158 MOVD R0, gobuf_ctxt(R5) 159 CMP R0, R0 // set condition codes for == test, needed by stack split 160 MOVD gobuf_pc(R5), R12 161 MOVD R12, CTR 162 BR (CTR) 163 164 // void mcall(fn func(*g)) 165 // Switch to m->g0's stack, call fn(g). 166 // Fn must never return. It should gogo(&g->sched) 167 // to keep running g. 168 TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 169 // Save caller state in g->sched 170 MOVD R1, (g_sched+gobuf_sp)(g) 171 MOVD LR, R31 172 MOVD R31, (g_sched+gobuf_pc)(g) 173 MOVD R0, (g_sched+gobuf_lr)(g) 174 MOVD g, (g_sched+gobuf_g)(g) 175 176 // Switch to m->g0 & its stack, call fn. 177 MOVD g, R3 178 MOVD g_m(g), R8 179 MOVD m_g0(R8), g 180 BL runtime·save_g(SB) 181 CMP g, R3 182 BNE 2(PC) 183 BR runtime·badmcall(SB) 184 MOVD fn+0(FP), R11 // context 185 MOVD 0(R11), R12 // code pointer 186 MOVD R12, CTR 187 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp 188 MOVDU R3, -8(R1) 189 MOVDU R0, -8(R1) 190 MOVDU R0, -8(R1) 191 MOVDU R0, -8(R1) 192 MOVDU R0, -8(R1) 193 BL (CTR) 194 MOVD 24(R1), R2 195 BR runtime·badmcall2(SB) 196 197 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 198 // of the G stack. We need to distinguish the routine that 199 // lives at the bottom of the G stack from the one that lives 200 // at the top of the system stack because the one at the top of 201 // the system stack terminates the stack walk (see topofstack()). 202 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 203 // We have several undefs here so that 16 bytes past 204 // $runtime·systemstack_switch lies within them whether or not the 205 // instructions that derive r2 from r12 are there. 206 UNDEF 207 UNDEF 208 UNDEF 209 BL (LR) // make sure this function is not leaf 210 RET 211 212 // func systemstack(fn func()) 213 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 214 MOVD fn+0(FP), R3 // R3 = fn 215 MOVD R3, R11 // context 216 MOVD g_m(g), R4 // R4 = m 217 218 MOVD m_gsignal(R4), R5 // R5 = gsignal 219 CMP g, R5 220 BEQ noswitch 221 222 MOVD m_g0(R4), R5 // R5 = g0 223 CMP g, R5 224 BEQ noswitch 225 226 MOVD m_curg(R4), R6 227 CMP g, R6 228 BEQ switch 229 230 // Bad: g is not gsignal, not g0, not curg. What is it? 231 // Hide call from linker nosplit analysis. 232 MOVD $runtime·badsystemstack(SB), R12 233 MOVD R12, CTR 234 BL (CTR) 235 BL runtime·abort(SB) 236 237 switch: 238 // save our state in g->sched. Pretend to 239 // be systemstack_switch if the G stack is scanned. 240 MOVD $runtime·systemstack_switch(SB), R6 241 ADD $16, R6 // get past prologue (including r2-setting instructions when they're there) 242 MOVD R6, (g_sched+gobuf_pc)(g) 243 MOVD R1, (g_sched+gobuf_sp)(g) 244 MOVD R0, (g_sched+gobuf_lr)(g) 245 MOVD g, (g_sched+gobuf_g)(g) 246 247 // switch to g0 248 MOVD R5, g 249 BL runtime·save_g(SB) 250 MOVD (g_sched+gobuf_sp)(g), R3 251 // make it look like mstart called systemstack on g0, to stop traceback 252 SUB $FIXED_FRAME, R3 253 MOVD $runtime·mstart(SB), R4 254 MOVD R4, 0(R3) 255 MOVD R3, R1 256 257 // call target function 258 MOVD 0(R11), R12 // code pointer 259 MOVD R12, CTR 260 BL (CTR) 261 262 // restore TOC pointer. It seems unlikely that we will use systemstack 263 // to call a function defined in another module, but the results of 264 // doing so would be so confusing that it's worth doing this. 265 MOVD g_m(g), R3 266 MOVD m_curg(R3), g 267 MOVD (g_sched+gobuf_sp)(g), R3 268 #ifndef GOOS_aix 269 MOVD 24(R3), R2 270 #endif 271 // switch back to g 272 MOVD g_m(g), R3 273 MOVD m_curg(R3), g 274 BL runtime·save_g(SB) 275 MOVD (g_sched+gobuf_sp)(g), R1 276 MOVD R0, (g_sched+gobuf_sp)(g) 277 RET 278 279 noswitch: 280 // already on m stack, just call directly 281 // On other arches we do a tail call here, but it appears to be 282 // impossible to tail call a function pointer in shared mode on 283 // ppc64 because the caller is responsible for restoring the TOC. 284 MOVD 0(R11), R12 // code pointer 285 MOVD R12, CTR 286 BL (CTR) 287 #ifndef GOOS_aix 288 MOVD 24(R1), R2 289 #endif 290 RET 291 292 /* 293 * support for morestack 294 */ 295 296 // Called during function prolog when more stack is needed. 297 // Caller has already loaded: 298 // R3: framesize, R4: argsize, R5: LR 299 // 300 // The traceback routines see morestack on a g0 as being 301 // the top of a stack (for example, morestack calling newstack 302 // calling the scheduler calling newm calling gc), so we must 303 // record an argument size. For that purpose, it has no arguments. 304 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 305 // Cannot grow scheduler stack (m->g0). 306 MOVD g_m(g), R7 307 MOVD m_g0(R7), R8 308 CMP g, R8 309 BNE 3(PC) 310 BL runtime·badmorestackg0(SB) 311 BL runtime·abort(SB) 312 313 // Cannot grow signal stack (m->gsignal). 314 MOVD m_gsignal(R7), R8 315 CMP g, R8 316 BNE 3(PC) 317 BL runtime·badmorestackgsignal(SB) 318 BL runtime·abort(SB) 319 320 // Called from f. 321 // Set g->sched to context in f. 322 MOVD R1, (g_sched+gobuf_sp)(g) 323 MOVD LR, R8 324 MOVD R8, (g_sched+gobuf_pc)(g) 325 MOVD R5, (g_sched+gobuf_lr)(g) 326 MOVD R11, (g_sched+gobuf_ctxt)(g) 327 328 // Called from f. 329 // Set m->morebuf to f's caller. 330 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 331 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 332 MOVD g, (m_morebuf+gobuf_g)(R7) 333 334 // Call newstack on m->g0's stack. 335 MOVD m_g0(R7), g 336 BL runtime·save_g(SB) 337 MOVD (g_sched+gobuf_sp)(g), R1 338 MOVDU R0, -(FIXED_FRAME+0)(R1) // create a call frame on g0 339 BL runtime·newstack(SB) 340 341 // Not reached, but make sure the return PC from the call to newstack 342 // is still in this function, and not the beginning of the next. 343 UNDEF 344 345 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 346 MOVD R0, R11 347 BR runtime·morestack(SB) 348 349 // reflectcall: call a function with the given argument list 350 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 351 // we don't have variable-sized frames, so we use a small number 352 // of constant-sized-frame functions to encode a few bits of size in the pc. 353 // Caution: ugly multiline assembly macros in your future! 354 355 #define DISPATCH(NAME,MAXSIZE) \ 356 MOVD $MAXSIZE, R31; \ 357 CMP R3, R31; \ 358 BGT 4(PC); \ 359 MOVD $NAME(SB), R12; \ 360 MOVD R12, CTR; \ 361 BR (CTR) 362 // Note: can't just "BR NAME(SB)" - bad inlining results. 363 364 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32 365 MOVWZ argsize+24(FP), R3 366 DISPATCH(runtime·call32, 32) 367 DISPATCH(runtime·call64, 64) 368 DISPATCH(runtime·call128, 128) 369 DISPATCH(runtime·call256, 256) 370 DISPATCH(runtime·call512, 512) 371 DISPATCH(runtime·call1024, 1024) 372 DISPATCH(runtime·call2048, 2048) 373 DISPATCH(runtime·call4096, 4096) 374 DISPATCH(runtime·call8192, 8192) 375 DISPATCH(runtime·call16384, 16384) 376 DISPATCH(runtime·call32768, 32768) 377 DISPATCH(runtime·call65536, 65536) 378 DISPATCH(runtime·call131072, 131072) 379 DISPATCH(runtime·call262144, 262144) 380 DISPATCH(runtime·call524288, 524288) 381 DISPATCH(runtime·call1048576, 1048576) 382 DISPATCH(runtime·call2097152, 2097152) 383 DISPATCH(runtime·call4194304, 4194304) 384 DISPATCH(runtime·call8388608, 8388608) 385 DISPATCH(runtime·call16777216, 16777216) 386 DISPATCH(runtime·call33554432, 33554432) 387 DISPATCH(runtime·call67108864, 67108864) 388 DISPATCH(runtime·call134217728, 134217728) 389 DISPATCH(runtime·call268435456, 268435456) 390 DISPATCH(runtime·call536870912, 536870912) 391 DISPATCH(runtime·call1073741824, 1073741824) 392 MOVD $runtime·badreflectcall(SB), R12 393 MOVD R12, CTR 394 BR (CTR) 395 396 #define CALLFN(NAME,MAXSIZE) \ 397 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 398 NO_LOCAL_POINTERS; \ 399 /* copy arguments to stack */ \ 400 MOVD arg+16(FP), R3; \ 401 MOVWZ argsize+24(FP), R4; \ 402 MOVD R1, R5; \ 403 CMP R4, $8; \ 404 BLT tailsetup; \ 405 /* copy 8 at a time if possible */ \ 406 ADD $(FIXED_FRAME-8), R5; \ 407 SUB $8, R3; \ 408 top: \ 409 MOVDU 8(R3), R7; \ 410 MOVDU R7, 8(R5); \ 411 SUB $8, R4; \ 412 CMP R4, $8; \ 413 BGE top; \ 414 /* handle remaining bytes */ \ 415 CMP $0, R4; \ 416 BEQ callfn; \ 417 ADD $7, R3; \ 418 ADD $7, R5; \ 419 BR tail; \ 420 tailsetup: \ 421 CMP $0, R4; \ 422 BEQ callfn; \ 423 ADD $(FIXED_FRAME-1), R5; \ 424 SUB $1, R3; \ 425 tail: \ 426 MOVBU 1(R3), R6; \ 427 MOVBU R6, 1(R5); \ 428 SUB $1, R4; \ 429 CMP $0, R4; \ 430 BGT tail; \ 431 callfn: \ 432 /* call function */ \ 433 MOVD f+8(FP), R11; \ 434 #ifdef GOOS_aix \ 435 /* AIX won't trigger a SIGSEGV if R11 = nil */ \ 436 /* So it manually triggers it */ \ 437 CMP R0, R11 \ 438 BNE 2(PC) \ 439 MOVD R0, 0(R0) \ 440 #endif \ 441 MOVD (R11), R12; \ 442 MOVD R12, CTR; \ 443 PCDATA $PCDATA_StackMapIndex, $0; \ 444 BL (CTR); \ 445 #ifndef GOOS_aix \ 446 MOVD 24(R1), R2; \ 447 #endif \ 448 /* copy return values back */ \ 449 MOVD argtype+0(FP), R7; \ 450 MOVD arg+16(FP), R3; \ 451 MOVWZ n+24(FP), R4; \ 452 MOVWZ retoffset+28(FP), R6; \ 453 ADD $FIXED_FRAME, R1, R5; \ 454 ADD R6, R5; \ 455 ADD R6, R3; \ 456 SUB R6, R4; \ 457 BL callRet<>(SB); \ 458 RET 459 460 // callRet copies return values back at the end of call*. This is a 461 // separate function so it can allocate stack space for the arguments 462 // to reflectcallmove. It does not follow the Go ABI; it expects its 463 // arguments in registers. 464 TEXT callRet<>(SB), NOSPLIT, $32-0 465 MOVD R7, FIXED_FRAME+0(R1) 466 MOVD R3, FIXED_FRAME+8(R1) 467 MOVD R5, FIXED_FRAME+16(R1) 468 MOVD R4, FIXED_FRAME+24(R1) 469 BL runtime·reflectcallmove(SB) 470 RET 471 472 CALLFN(·call32, 32) 473 CALLFN(·call64, 64) 474 CALLFN(·call128, 128) 475 CALLFN(·call256, 256) 476 CALLFN(·call512, 512) 477 CALLFN(·call1024, 1024) 478 CALLFN(·call2048, 2048) 479 CALLFN(·call4096, 4096) 480 CALLFN(·call8192, 8192) 481 CALLFN(·call16384, 16384) 482 CALLFN(·call32768, 32768) 483 CALLFN(·call65536, 65536) 484 CALLFN(·call131072, 131072) 485 CALLFN(·call262144, 262144) 486 CALLFN(·call524288, 524288) 487 CALLFN(·call1048576, 1048576) 488 CALLFN(·call2097152, 2097152) 489 CALLFN(·call4194304, 4194304) 490 CALLFN(·call8388608, 8388608) 491 CALLFN(·call16777216, 16777216) 492 CALLFN(·call33554432, 33554432) 493 CALLFN(·call67108864, 67108864) 494 CALLFN(·call134217728, 134217728) 495 CALLFN(·call268435456, 268435456) 496 CALLFN(·call536870912, 536870912) 497 CALLFN(·call1073741824, 1073741824) 498 499 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4 500 MOVW cycles+0(FP), R7 501 // POWER does not have a pause/yield instruction equivalent. 502 // Instead, we can lower the program priority by setting the 503 // Program Priority Register prior to the wait loop and set it 504 // back to default afterwards. On Linux, the default priority is 505 // medium-low. For details, see page 837 of the ISA 3.0. 506 OR R1, R1, R1 // Set PPR priority to low 507 again: 508 SUB $1, R7 509 CMP $0, R7 510 BNE again 511 OR R6, R6, R6 // Set PPR priority back to medium-low 512 RET 513 514 // void jmpdefer(fv, sp); 515 // called from deferreturn. 516 // 1. grab stored LR for caller 517 // 2. sub 8 bytes to get back to either nop or toc reload before deferreturn 518 // 3. BR to fn 519 // When dynamically linking Go, it is not sufficient to rewind to the BL 520 // deferreturn -- we might be jumping between modules and so we need to reset 521 // the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* 522 // the BL deferreturn and jmpdefer rewinds to that. 523 TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 524 MOVD 0(R1), R31 525 SUB $8, R31 526 MOVD R31, LR 527 528 MOVD fv+0(FP), R11 529 MOVD argp+8(FP), R1 530 SUB $FIXED_FRAME, R1 531 #ifdef GOOS_aix 532 // AIX won't trigger a SIGSEGV if R11 = nil 533 // So it manually triggers it 534 CMP R0, R11 535 BNE 2(PC) 536 MOVD R0, 0(R0) 537 #endif 538 MOVD 0(R11), R12 539 MOVD R12, CTR 540 BR (CTR) 541 542 // Save state of caller into g->sched. Smashes R31. 543 TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 544 MOVD LR, R31 545 MOVD R31, (g_sched+gobuf_pc)(g) 546 MOVD R1, (g_sched+gobuf_sp)(g) 547 MOVD R0, (g_sched+gobuf_lr)(g) 548 MOVD R0, (g_sched+gobuf_ret)(g) 549 // Assert ctxt is zero. See func save. 550 MOVD (g_sched+gobuf_ctxt)(g), R31 551 CMP R0, R31 552 BEQ 2(PC) 553 BL runtime·badctxt(SB) 554 RET 555 556 // func asmcgocall(fn, arg unsafe.Pointer) int32 557 // Call fn(arg) on the scheduler stack, 558 // aligned appropriately for the gcc ABI. 559 // See cgocall.go for more details. 560 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 561 MOVD fn+0(FP), R3 562 MOVD arg+8(FP), R4 563 564 MOVD R1, R7 // save original stack pointer 565 MOVD g, R5 566 567 // Figure out if we need to switch to m->g0 stack. 568 // We get called to create new OS threads too, and those 569 // come in on the m->g0 stack already. 570 // Moreover, if it's called inside the signal handler, it must not switch 571 // to g0 as it can be in use by another syscall. 572 MOVD g_m(g), R8 573 MOVD m_gsignal(R8), R6 574 CMP R6, g 575 BEQ g0 576 MOVD m_g0(R8), R6 577 CMP R6, g 578 BEQ g0 579 BL gosave<>(SB) 580 MOVD R6, g 581 BL runtime·save_g(SB) 582 MOVD (g_sched+gobuf_sp)(g), R1 583 584 // Now on a scheduling stack (a pthread-created stack). 585 g0: 586 // Save room for two of our pointers, plus 32 bytes of callee 587 // save area that lives on the caller stack. 588 #ifdef GOOS_aix 589 // Create a fake LR to improve backtrace. 590 MOVD $runtime·asmcgocall(SB), R6 591 MOVD R6, 16(R1) 592 #endif 593 SUB $48, R1 594 RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI 595 MOVD R5, 40(R1) // save old g on stack 596 MOVD (g_stack+stack_hi)(R5), R5 597 SUB R7, R5 598 MOVD R5, 32(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 599 #ifdef GOOS_aix 600 MOVD R7, 0(R1) // Save frame pointer to allow manual backtrace with gdb 601 #else 602 MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?) 603 #endif 604 // This is a "global call", so put the global entry point in r12 605 MOVD R3, R12 606 607 #ifdef GOARCH_ppc64 608 // ppc64 use elf ABI v1. we must get the real entry address from 609 // first slot of the function descriptor before call. 610 #ifndef GOOS_aix 611 // aix just passes the function pointer for the moment, see golang.org/cl/146898 for details. 612 MOVD 8(R12), R2 613 MOVD (R12), R12 614 #endif 615 #endif 616 MOVD R12, CTR 617 MOVD R4, R3 // arg in r3 618 BL (CTR) 619 620 // C code can clobber R0, so set it back to 0. F27-F31 are 621 // callee save, so we don't need to recover those. 622 XOR R0, R0 623 // Restore g, stack pointer, toc pointer. 624 // R3 is errno, so don't touch it 625 MOVD 40(R1), g 626 MOVD (g_stack+stack_hi)(g), R5 627 MOVD 32(R1), R6 628 SUB R6, R5 629 #ifndef GOOS_aix 630 MOVD 24(R5), R2 631 #endif 632 MOVD R5, R1 633 BL runtime·save_g(SB) 634 635 MOVW R3, ret+16(FP) 636 RET 637 638 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 639 // Turn the fn into a Go func (by taking its address) and call 640 // cgocallback_gofunc. 641 TEXT runtime·cgocallback(SB),NOSPLIT,$32-32 642 MOVD $fn+0(FP), R3 643 MOVD R3, FIXED_FRAME+0(R1) 644 MOVD frame+8(FP), R3 645 MOVD R3, FIXED_FRAME+8(R1) 646 MOVD framesize+16(FP), R3 647 MOVD R3, FIXED_FRAME+16(R1) 648 MOVD ctxt+24(FP), R3 649 MOVD R3, FIXED_FRAME+24(R1) 650 MOVD $runtime·cgocallback_gofunc(SB), R12 651 MOVD R12, CTR 652 BL (CTR) 653 RET 654 655 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 656 // See cgocall.go for more details. 657 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32 658 NO_LOCAL_POINTERS 659 660 // Load m and g from thread-local storage. 661 MOVBZ runtime·iscgo(SB), R3 662 CMP R3, $0 663 BEQ nocgo 664 BL runtime·load_g(SB) 665 nocgo: 666 667 // If g is nil, Go did not create the current thread. 668 // Call needm to obtain one for temporary use. 669 // In this case, we're running on the thread stack, so there's 670 // lots of space, but the linker doesn't know. Hide the call from 671 // the linker analysis by using an indirect call. 672 CMP g, $0 673 BEQ needm 674 675 MOVD g_m(g), R8 676 MOVD R8, savedm-8(SP) 677 BR havem 678 679 needm: 680 MOVD g, savedm-8(SP) // g is zero, so is m. 681 MOVD $runtime·needm(SB), R12 682 MOVD R12, CTR 683 BL (CTR) 684 685 // Set m->sched.sp = SP, so that if a panic happens 686 // during the function we are about to execute, it will 687 // have a valid SP to run on the g0 stack. 688 // The next few lines (after the havem label) 689 // will save this SP onto the stack and then write 690 // the same SP back to m->sched.sp. That seems redundant, 691 // but if an unrecovered panic happens, unwindm will 692 // restore the g->sched.sp from the stack location 693 // and then systemstack will try to use it. If we don't set it here, 694 // that restored SP will be uninitialized (typically 0) and 695 // will not be usable. 696 MOVD g_m(g), R8 697 MOVD m_g0(R8), R3 698 MOVD R1, (g_sched+gobuf_sp)(R3) 699 700 havem: 701 // Now there's a valid m, and we're running on its m->g0. 702 // Save current m->g0->sched.sp on stack and then set it to SP. 703 // Save current sp in m->g0->sched.sp in preparation for 704 // switch back to m->curg stack. 705 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 706 MOVD m_g0(R8), R3 707 MOVD (g_sched+gobuf_sp)(R3), R4 708 MOVD R4, savedsp-16(SP) 709 MOVD R1, (g_sched+gobuf_sp)(R3) 710 711 // Switch to m->curg stack and call runtime.cgocallbackg. 712 // Because we are taking over the execution of m->curg 713 // but *not* resuming what had been running, we need to 714 // save that information (m->curg->sched) so we can restore it. 715 // We can restore m->curg->sched.sp easily, because calling 716 // runtime.cgocallbackg leaves SP unchanged upon return. 717 // To save m->curg->sched.pc, we push it onto the stack. 718 // This has the added benefit that it looks to the traceback 719 // routine like cgocallbackg is going to return to that 720 // PC (because the frame we allocate below has the same 721 // size as cgocallback_gofunc's frame declared above) 722 // so that the traceback will seamlessly trace back into 723 // the earlier calls. 724 // 725 // In the new goroutine, -8(SP) is unused (where SP refers to 726 // m->curg's SP while we're setting it up, before we've adjusted it). 727 MOVD m_curg(R8), g 728 BL runtime·save_g(SB) 729 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 730 MOVD (g_sched+gobuf_pc)(g), R5 731 MOVD R5, -(FIXED_FRAME+16)(R4) 732 MOVD ctxt+24(FP), R3 733 MOVD R3, -16(R4) 734 MOVD $-(FIXED_FRAME+16)(R4), R1 735 BL runtime·cgocallbackg(SB) 736 737 // Restore g->sched (== m->curg->sched) from saved values. 738 MOVD 0(R1), R5 739 MOVD R5, (g_sched+gobuf_pc)(g) 740 MOVD $(FIXED_FRAME+16)(R1), R4 741 MOVD R4, (g_sched+gobuf_sp)(g) 742 743 // Switch back to m->g0's stack and restore m->g0->sched.sp. 744 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 745 // so we do not have to restore it.) 746 MOVD g_m(g), R8 747 MOVD m_g0(R8), g 748 BL runtime·save_g(SB) 749 MOVD (g_sched+gobuf_sp)(g), R1 750 MOVD savedsp-16(SP), R4 751 MOVD R4, (g_sched+gobuf_sp)(g) 752 753 // If the m on entry was nil, we called needm above to borrow an m 754 // for the duration of the call. Since the call is over, return it with dropm. 755 MOVD savedm-8(SP), R6 756 CMP R6, $0 757 BNE droppedm 758 MOVD $runtime·dropm(SB), R12 759 MOVD R12, CTR 760 BL (CTR) 761 droppedm: 762 763 // Done! 764 RET 765 766 // void setg(G*); set g. for use by needm. 767 TEXT runtime·setg(SB), NOSPLIT, $0-8 768 MOVD gg+0(FP), g 769 // This only happens if iscgo, so jump straight to save_g 770 BL runtime·save_g(SB) 771 RET 772 773 #ifdef GOARCH_ppc64 774 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 775 DWORD $_setg_gcc<>(SB) 776 DWORD $0 777 DWORD $0 778 #endif 779 780 // void setg_gcc(G*); set g in C TLS. 781 // Must obey the gcc calling convention. 782 #ifdef GOARCH_ppc64le 783 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 784 #else 785 TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 786 #endif 787 // The standard prologue clobbers R31, which is callee-save in 788 // the C ABI, so we have to use $-8-0 and save LR ourselves. 789 MOVD LR, R4 790 // Also save g and R31, since they're callee-save in C ABI 791 MOVD R31, R5 792 MOVD g, R6 793 794 MOVD R3, g 795 BL runtime·save_g(SB) 796 797 MOVD R6, g 798 MOVD R5, R31 799 MOVD R4, LR 800 RET 801 802 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 803 MOVW (R0), R0 804 UNDEF 805 806 #define TBR 268 807 808 // int64 runtime·cputicks(void) 809 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 810 MOVD SPR(TBR), R3 811 MOVD R3, ret+0(FP) 812 RET 813 814 // AES hashing not implemented for ppc64 815 TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0 816 MOVW (R0), R1 817 TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0 818 MOVW (R0), R1 819 TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0 820 MOVW (R0), R1 821 TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0 822 MOVW (R0), R1 823 824 TEXT runtime·return0(SB), NOSPLIT, $0 825 MOVW $0, R3 826 RET 827 828 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 829 // Must obey the gcc calling convention. 830 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 831 // g (R30) and R31 are callee-save in the C ABI, so save them 832 MOVD g, R4 833 MOVD R31, R5 834 MOVD LR, R6 835 836 BL runtime·load_g(SB) // clobbers g (R30), R31 837 MOVD g_m(g), R3 838 MOVD m_curg(R3), R3 839 MOVD (g_stack+stack_hi)(R3), R3 840 841 MOVD R4, g 842 MOVD R5, R31 843 MOVD R6, LR 844 RET 845 846 // The top-most function running on a goroutine 847 // returns to goexit+PCQuantum. 848 // 849 // When dynamically linking Go, it can be returned to from a function 850 // implemented in a different module and so needs to reload the TOC pointer 851 // from the stack (although this function declares that it does not set up x-a 852 // frame, newproc1 does in fact allocate one for goexit and saves the TOC 853 // pointer in the correct place). 854 // goexit+_PCQuantum is halfway through the usual global entry point prologue 855 // that derives r2 from r12 which is a bit silly, but not harmful. 856 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0 857 MOVD 24(R1), R2 858 BL runtime·goexit1(SB) // does not return 859 // traceback from goexit1 must hit code range of goexit 860 MOVD R0, R0 // NOP 861 862 TEXT runtime·sigreturn(SB),NOSPLIT,$0-0 863 RET 864 865 // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the 866 // module containing runtime) to the frame that goexit will execute in when 867 // the goroutine exits. It's implemented in assembly mainly because that's the 868 // easiest way to get access to R2. 869 TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8 870 MOVD sp+0(FP), R3 871 MOVD R2, 24(R3) 872 RET 873 874 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 875 ADD $-8, R1 876 MOVD R31, 0(R1) 877 MOVD runtime·lastmoduledatap(SB), R4 878 MOVD R3, moduledata_next(R4) 879 MOVD R3, runtime·lastmoduledatap(SB) 880 MOVD 0(R1), R31 881 ADD $8, R1 882 RET 883 884 TEXT ·checkASM(SB),NOSPLIT,$0-1 885 MOVW $1, R3 886 MOVB R3, ret+0(FP) 887 RET 888 889 // gcWriteBarrier performs a heap pointer write and informs the GC. 890 // 891 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 892 // - R20 is the destination of the write 893 // - R21 is the value being written at R20. 894 // It clobbers condition codes. 895 // It does not clobber R0 through R15, 896 // but may clobber any other register, *including* R31. 897 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$112 898 // The standard prologue clobbers R31. 899 // We use R16 and R17 as scratch registers. 900 MOVD g_m(g), R16 901 MOVD m_p(R16), R16 902 MOVD (p_wbBuf+wbBuf_next)(R16), R17 903 // Increment wbBuf.next position. 904 ADD $16, R17 905 MOVD R17, (p_wbBuf+wbBuf_next)(R16) 906 MOVD (p_wbBuf+wbBuf_end)(R16), R16 907 CMP R16, R17 908 // Record the write. 909 MOVD R21, -16(R17) // Record value 910 MOVD (R20), R16 // TODO: This turns bad writes into bad reads. 911 MOVD R16, -8(R17) // Record *slot 912 // Is the buffer full? (flags set in CMP above) 913 BEQ flush 914 ret: 915 // Do the write. 916 MOVD R21, (R20) 917 RET 918 919 flush: 920 // Save registers R0 through R15 since these were not saved by the caller. 921 // We don't save all registers on ppc64 because it takes too much space. 922 MOVD R20, (FIXED_FRAME+0)(R1) // Also first argument to wbBufFlush 923 MOVD R21, (FIXED_FRAME+8)(R1) // Also second argument to wbBufFlush 924 // R0 is always 0, so no need to spill. 925 // R1 is SP. 926 // R2 is SB. 927 MOVD R3, (FIXED_FRAME+16)(R1) 928 MOVD R4, (FIXED_FRAME+24)(R1) 929 MOVD R5, (FIXED_FRAME+32)(R1) 930 MOVD R6, (FIXED_FRAME+40)(R1) 931 MOVD R7, (FIXED_FRAME+48)(R1) 932 MOVD R8, (FIXED_FRAME+56)(R1) 933 MOVD R9, (FIXED_FRAME+64)(R1) 934 MOVD R10, (FIXED_FRAME+72)(R1) 935 MOVD R11, (FIXED_FRAME+80)(R1) 936 MOVD R12, (FIXED_FRAME+88)(R1) 937 // R13 is REGTLS 938 MOVD R14, (FIXED_FRAME+96)(R1) 939 MOVD R15, (FIXED_FRAME+104)(R1) 940 941 // This takes arguments R20 and R21. 942 CALL runtime·wbBufFlush(SB) 943 944 MOVD (FIXED_FRAME+0)(R1), R20 945 MOVD (FIXED_FRAME+8)(R1), R21 946 MOVD (FIXED_FRAME+16)(R1), R3 947 MOVD (FIXED_FRAME+24)(R1), R4 948 MOVD (FIXED_FRAME+32)(R1), R5 949 MOVD (FIXED_FRAME+40)(R1), R6 950 MOVD (FIXED_FRAME+48)(R1), R7 951 MOVD (FIXED_FRAME+56)(R1), R8 952 MOVD (FIXED_FRAME+64)(R1), R9 953 MOVD (FIXED_FRAME+72)(R1), R10 954 MOVD (FIXED_FRAME+80)(R1), R11 955 MOVD (FIXED_FRAME+88)(R1), R12 956 MOVD (FIXED_FRAME+96)(R1), R14 957 MOVD (FIXED_FRAME+104)(R1), R15 958 JMP ret