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