github.com/mtsmfm/go/src@v0.0.0-20221020090648-44bdcb9f8fde/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 //go: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|TOPFRAME,$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 BL runtime·newproc(SB) 97 ADD $(8+FIXED_FRAME), R1 98 99 // start this M 100 BL runtime·mstart(SB) 101 102 MOVD R0, 0(R0) 103 RET 104 105 DATA runtime·mainPC+0(SB)/8,$runtime·main<ABIInternal>(SB) 106 GLOBL runtime·mainPC(SB),RODATA,$8 107 108 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 109 TW $31, R0, R0 110 RET 111 112 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 113 RET 114 115 // Any changes must be reflected to runtime/cgo/gcc_aix_ppc64.S:.crosscall_ppc64 116 TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0 117 // crosscall_ppc64 and crosscall2 need to reginit, but can't 118 // get at the 'runtime.reginit' symbol. 119 BR runtime·reginit(SB) 120 121 TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0 122 // set R0 to zero, it's expected by the toolchain 123 XOR R0, R0 124 RET 125 126 TEXT runtime·mstart(SB),NOSPLIT|TOPFRAME,$0 127 BL runtime·mstart0(SB) 128 RET // not reached 129 130 /* 131 * go-routine 132 */ 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), R6 139 MOVD 0(R6), R4 // make sure g != nil 140 BR gogo<>(SB) 141 142 TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0 143 MOVD R6, g 144 BL runtime·save_g(SB) 145 146 MOVD gobuf_sp(R5), R1 147 MOVD gobuf_lr(R5), R31 148 #ifndef GOOS_aix 149 MOVD 24(R1), R2 // restore R2 150 #endif 151 MOVD R31, LR 152 MOVD gobuf_ret(R5), R3 153 MOVD gobuf_ctxt(R5), R11 154 MOVD R0, gobuf_sp(R5) 155 MOVD R0, gobuf_ret(R5) 156 MOVD R0, gobuf_lr(R5) 157 MOVD R0, gobuf_ctxt(R5) 158 CMP R0, R0 // set condition codes for == test, needed by stack split 159 MOVD gobuf_pc(R5), R12 160 MOVD R12, CTR 161 BR (CTR) 162 163 // void mcall(fn func(*g)) 164 // Switch to m->g0's stack, call fn(g). 165 // Fn must never return. It should gogo(&g->sched) 166 // to keep running g. 167 TEXT runtime·mcall<ABIInternal>(SB), NOSPLIT|NOFRAME, $0-8 168 // Save caller state in g->sched 169 // R11 should be safe across save_g?? 170 MOVD R3, R11 171 MOVD R1, (g_sched+gobuf_sp)(g) 172 MOVD LR, R31 173 MOVD R31, (g_sched+gobuf_pc)(g) 174 MOVD R0, (g_sched+gobuf_lr)(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 0(R11), R12 // code pointer 185 MOVD R12, CTR 186 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp 187 // Don't need to do anything special for regabiargs here 188 // R3 is g; stack is set anyway 189 MOVDU R3, -8(R1) 190 MOVDU R0, -8(R1) 191 MOVDU R0, -8(R1) 192 MOVDU R0, -8(R1) 193 MOVDU R0, -8(R1) 194 BL (CTR) 195 MOVD 24(R1), R2 196 BR runtime·badmcall2(SB) 197 198 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 199 // of the G stack. We need to distinguish the routine that 200 // lives at the bottom of the G stack from the one that lives 201 // at the top of the system stack because the one at the top of 202 // the system stack terminates the stack walk (see topofstack()). 203 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 204 // We have several undefs here so that 16 bytes past 205 // $runtime·systemstack_switch lies within them whether or not the 206 // instructions that derive r2 from r12 are there. 207 UNDEF 208 UNDEF 209 UNDEF 210 BL (LR) // make sure this function is not leaf 211 RET 212 213 // func systemstack(fn func()) 214 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 215 MOVD fn+0(FP), R3 // R3 = fn 216 MOVD R3, R11 // context 217 MOVD g_m(g), R4 // R4 = m 218 219 MOVD m_gsignal(R4), R5 // R5 = gsignal 220 CMP g, R5 221 BEQ noswitch 222 223 MOVD m_g0(R4), R5 // R5 = g0 224 CMP g, R5 225 BEQ noswitch 226 227 MOVD m_curg(R4), R6 228 CMP g, R6 229 BEQ switch 230 231 // Bad: g is not gsignal, not g0, not curg. What is it? 232 // Hide call from linker nosplit analysis. 233 MOVD $runtime·badsystemstack(SB), R12 234 MOVD R12, CTR 235 BL (CTR) 236 BL runtime·abort(SB) 237 238 switch: 239 // save our state in g->sched. Pretend to 240 // be systemstack_switch if the G stack is scanned. 241 BL gosave_systemstack_switch<>(SB) 242 243 // switch to g0 244 MOVD R5, g 245 BL runtime·save_g(SB) 246 MOVD (g_sched+gobuf_sp)(g), 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 #ifndef GOOS_aix 260 MOVD 24(R3), R2 261 #endif 262 // switch back to g 263 MOVD g_m(g), R3 264 MOVD m_curg(R3), g 265 BL runtime·save_g(SB) 266 MOVD (g_sched+gobuf_sp)(g), R1 267 MOVD R0, (g_sched+gobuf_sp)(g) 268 RET 269 270 noswitch: 271 // already on m stack, just call directly 272 // On other arches we do a tail call here, but it appears to be 273 // impossible to tail call a function pointer in shared mode on 274 // ppc64 because the caller is responsible for restoring the TOC. 275 MOVD 0(R11), R12 // code pointer 276 MOVD R12, CTR 277 BL (CTR) 278 #ifndef GOOS_aix 279 MOVD 24(R1), R2 280 #endif 281 RET 282 283 /* 284 * support for morestack 285 */ 286 287 // Called during function prolog when more stack is needed. 288 // Caller has already loaded: 289 // R3: framesize, R4: argsize, R5: LR 290 // 291 // The traceback routines see morestack on a g0 as being 292 // the top of a stack (for example, morestack calling newstack 293 // calling the scheduler calling newm calling gc), so we must 294 // record an argument size. For that purpose, it has no arguments. 295 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 296 // Cannot grow scheduler stack (m->g0). 297 MOVD g_m(g), R7 298 MOVD m_g0(R7), R8 299 CMP g, R8 300 BNE 3(PC) 301 BL runtime·badmorestackg0(SB) 302 BL runtime·abort(SB) 303 304 // Cannot grow signal stack (m->gsignal). 305 MOVD m_gsignal(R7), R8 306 CMP g, R8 307 BNE 3(PC) 308 BL runtime·badmorestackgsignal(SB) 309 BL runtime·abort(SB) 310 311 // Called from f. 312 // Set g->sched to context in f. 313 MOVD R1, (g_sched+gobuf_sp)(g) 314 MOVD LR, R8 315 MOVD R8, (g_sched+gobuf_pc)(g) 316 MOVD R5, (g_sched+gobuf_lr)(g) 317 MOVD R11, (g_sched+gobuf_ctxt)(g) 318 319 // Called from f. 320 // Set m->morebuf to f's caller. 321 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 322 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 323 MOVD g, (m_morebuf+gobuf_g)(R7) 324 325 // Call newstack on m->g0's stack. 326 MOVD m_g0(R7), g 327 BL runtime·save_g(SB) 328 MOVD (g_sched+gobuf_sp)(g), R1 329 MOVDU R0, -(FIXED_FRAME+0)(R1) // create a call frame on g0 330 BL runtime·newstack(SB) 331 332 // Not reached, but make sure the return PC from the call to newstack 333 // is still in this function, and not the beginning of the next. 334 UNDEF 335 336 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 337 // Force SPWRITE. This function doesn't actually write SP, 338 // but it is called with a special calling convention where 339 // the caller doesn't save LR on stack but passes it as a 340 // register (R5), and the unwinder currently doesn't understand. 341 // Make it SPWRITE to stop unwinding. (See issue 54332) 342 MOVD R1, R1 343 344 MOVD R0, R11 345 BR runtime·morestack(SB) 346 347 // reflectcall: call a function with the given argument list 348 // func call(stackArgsType *_type, f *FuncVal, stackArgs *byte, stackArgsSize, stackRetOffset, frameSize uint32, regArgs *abi.RegArgs). 349 // we don't have variable-sized frames, so we use a small number 350 // of constant-sized-frame functions to encode a few bits of size in the pc. 351 // Caution: ugly multiline assembly macros in your future! 352 353 #define DISPATCH(NAME,MAXSIZE) \ 354 MOVD $MAXSIZE, R31; \ 355 CMP R3, R31; \ 356 BGT 4(PC); \ 357 MOVD $NAME(SB), R12; \ 358 MOVD R12, CTR; \ 359 BR (CTR) 360 // Note: can't just "BR NAME(SB)" - bad inlining results. 361 362 TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-48 363 MOVWZ frameSize+32(FP), R3 364 DISPATCH(runtime·call16, 16) 365 DISPATCH(runtime·call32, 32) 366 DISPATCH(runtime·call64, 64) 367 DISPATCH(runtime·call128, 128) 368 DISPATCH(runtime·call256, 256) 369 DISPATCH(runtime·call512, 512) 370 DISPATCH(runtime·call1024, 1024) 371 DISPATCH(runtime·call2048, 2048) 372 DISPATCH(runtime·call4096, 4096) 373 DISPATCH(runtime·call8192, 8192) 374 DISPATCH(runtime·call16384, 16384) 375 DISPATCH(runtime·call32768, 32768) 376 DISPATCH(runtime·call65536, 65536) 377 DISPATCH(runtime·call131072, 131072) 378 DISPATCH(runtime·call262144, 262144) 379 DISPATCH(runtime·call524288, 524288) 380 DISPATCH(runtime·call1048576, 1048576) 381 DISPATCH(runtime·call2097152, 2097152) 382 DISPATCH(runtime·call4194304, 4194304) 383 DISPATCH(runtime·call8388608, 8388608) 384 DISPATCH(runtime·call16777216, 16777216) 385 DISPATCH(runtime·call33554432, 33554432) 386 DISPATCH(runtime·call67108864, 67108864) 387 DISPATCH(runtime·call134217728, 134217728) 388 DISPATCH(runtime·call268435456, 268435456) 389 DISPATCH(runtime·call536870912, 536870912) 390 DISPATCH(runtime·call1073741824, 1073741824) 391 MOVD $runtime·badreflectcall(SB), R12 392 MOVD R12, CTR 393 BR (CTR) 394 395 #define CALLFN(NAME,MAXSIZE) \ 396 TEXT NAME(SB), WRAPPER, $MAXSIZE-48; \ 397 NO_LOCAL_POINTERS; \ 398 /* copy arguments to stack */ \ 399 MOVD stackArgs+16(FP), R3; \ 400 MOVWZ stackArgsSize+24(FP), R4; \ 401 MOVD R1, R5; \ 402 CMP R4, $8; \ 403 BLT tailsetup; \ 404 /* copy 8 at a time if possible */ \ 405 ADD $(FIXED_FRAME-8), R5; \ 406 SUB $8, R3; \ 407 top: \ 408 MOVDU 8(R3), R7; \ 409 MOVDU R7, 8(R5); \ 410 SUB $8, R4; \ 411 CMP R4, $8; \ 412 BGE top; \ 413 /* handle remaining bytes */ \ 414 CMP $0, R4; \ 415 BEQ callfn; \ 416 ADD $7, R3; \ 417 ADD $7, R5; \ 418 BR tail; \ 419 tailsetup: \ 420 CMP $0, R4; \ 421 BEQ callfn; \ 422 ADD $(FIXED_FRAME-1), R5; \ 423 SUB $1, R3; \ 424 tail: \ 425 MOVBU 1(R3), R6; \ 426 MOVBU R6, 1(R5); \ 427 SUB $1, R4; \ 428 CMP $0, R4; \ 429 BGT tail; \ 430 callfn: \ 431 /* call function */ \ 432 MOVD f+8(FP), R11; \ 433 #ifdef GOOS_aix \ 434 /* AIX won't trigger a SIGSEGV if R11 = nil */ \ 435 /* So it manually triggers it */ \ 436 CMP R0, R11 \ 437 BNE 2(PC) \ 438 MOVD R0, 0(R0) \ 439 #endif \ 440 MOVD regArgs+40(FP), R20; \ 441 BL runtime·unspillArgs(SB); \ 442 MOVD (R11), R12; \ 443 MOVD R12, CTR; \ 444 PCDATA $PCDATA_StackMapIndex, $0; \ 445 BL (CTR); \ 446 #ifndef GOOS_aix \ 447 MOVD 24(R1), R2; \ 448 #endif \ 449 /* copy return values back */ \ 450 MOVD regArgs+40(FP), R20; \ 451 BL runtime·spillArgs(SB); \ 452 MOVD stackArgsType+0(FP), R7; \ 453 MOVD stackArgs+16(FP), R3; \ 454 MOVWZ stackArgsSize+24(FP), R4; \ 455 MOVWZ stackRetOffset+28(FP), R6; \ 456 ADD $FIXED_FRAME, R1, R5; \ 457 ADD R6, R5; \ 458 ADD R6, R3; \ 459 SUB R6, R4; \ 460 BL callRet<>(SB); \ 461 RET 462 463 // callRet copies return values back at the end of call*. This is a 464 // separate function so it can allocate stack space for the arguments 465 // to reflectcallmove. It does not follow the Go ABI; it expects its 466 // arguments in registers. 467 TEXT callRet<>(SB), NOSPLIT, $40-0 468 NO_LOCAL_POINTERS 469 MOVD R7, FIXED_FRAME+0(R1) 470 MOVD R3, FIXED_FRAME+8(R1) 471 MOVD R5, FIXED_FRAME+16(R1) 472 MOVD R4, FIXED_FRAME+24(R1) 473 MOVD R20, FIXED_FRAME+32(R1) 474 BL runtime·reflectcallmove(SB) 475 RET 476 477 CALLFN(·call16, 16) 478 CALLFN(·call32, 32) 479 CALLFN(·call64, 64) 480 CALLFN(·call128, 128) 481 CALLFN(·call256, 256) 482 CALLFN(·call512, 512) 483 CALLFN(·call1024, 1024) 484 CALLFN(·call2048, 2048) 485 CALLFN(·call4096, 4096) 486 CALLFN(·call8192, 8192) 487 CALLFN(·call16384, 16384) 488 CALLFN(·call32768, 32768) 489 CALLFN(·call65536, 65536) 490 CALLFN(·call131072, 131072) 491 CALLFN(·call262144, 262144) 492 CALLFN(·call524288, 524288) 493 CALLFN(·call1048576, 1048576) 494 CALLFN(·call2097152, 2097152) 495 CALLFN(·call4194304, 4194304) 496 CALLFN(·call8388608, 8388608) 497 CALLFN(·call16777216, 16777216) 498 CALLFN(·call33554432, 33554432) 499 CALLFN(·call67108864, 67108864) 500 CALLFN(·call134217728, 134217728) 501 CALLFN(·call268435456, 268435456) 502 CALLFN(·call536870912, 536870912) 503 CALLFN(·call1073741824, 1073741824) 504 505 TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4 506 MOVW cycles+0(FP), R7 507 // POWER does not have a pause/yield instruction equivalent. 508 // Instead, we can lower the program priority by setting the 509 // Program Priority Register prior to the wait loop and set it 510 // back to default afterwards. On Linux, the default priority is 511 // medium-low. For details, see page 837 of the ISA 3.0. 512 OR R1, R1, R1 // Set PPR priority to low 513 again: 514 SUB $1, R7 515 CMP $0, R7 516 BNE again 517 OR R6, R6, R6 // Set PPR priority back to medium-low 518 RET 519 520 // Save state of caller into g->sched, 521 // but using fake PC from systemstack_switch. 522 // Must only be called from functions with no locals ($0) 523 // or else unwinding from systemstack_switch is incorrect. 524 // Smashes R31. 525 TEXT gosave_systemstack_switch<>(SB),NOSPLIT|NOFRAME,$0 526 MOVD $runtime·systemstack_switch(SB), R31 527 ADD $16, R31 // get past prologue (including r2-setting instructions when they're there) 528 MOVD R31, (g_sched+gobuf_pc)(g) 529 MOVD R1, (g_sched+gobuf_sp)(g) 530 MOVD R0, (g_sched+gobuf_lr)(g) 531 MOVD R0, (g_sched+gobuf_ret)(g) 532 // Assert ctxt is zero. See func save. 533 MOVD (g_sched+gobuf_ctxt)(g), R31 534 CMP R0, R31 535 BEQ 2(PC) 536 BL runtime·abort(SB) 537 RET 538 539 #ifdef GOOS_aix 540 #define asmcgocallSaveOffset cgoCalleeStackSize + 8 541 #else 542 #define asmcgocallSaveOffset cgoCalleeStackSize 543 #endif 544 545 // func asmcgocall(fn, arg unsafe.Pointer) int32 546 // Call fn(arg) on the scheduler stack, 547 // aligned appropriately for the gcc ABI. 548 // See cgocall.go for more details. 549 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 550 MOVD fn+0(FP), R3 551 MOVD arg+8(FP), R4 552 553 MOVD R1, R7 // save original stack pointer 554 MOVD g, R5 555 556 // Figure out if we need to switch to m->g0 stack. 557 // We get called to create new OS threads too, and those 558 // come in on the m->g0 stack already. Or we might already 559 // be on the m->gsignal stack. 560 MOVD g_m(g), R8 561 MOVD m_gsignal(R8), R6 562 CMP R6, g 563 BEQ g0 564 MOVD m_g0(R8), R6 565 CMP R6, g 566 BEQ g0 567 BL gosave_systemstack_switch<>(SB) 568 MOVD R6, g 569 BL runtime·save_g(SB) 570 MOVD (g_sched+gobuf_sp)(g), R1 571 572 // Now on a scheduling stack (a pthread-created stack). 573 g0: 574 #ifdef GOOS_aix 575 // Create a fake LR to improve backtrace. 576 MOVD $runtime·asmcgocall(SB), R6 577 MOVD R6, 16(R1) 578 // AIX also save one argument on the stack. 579 SUB $8, R1 580 #endif 581 // Save room for two of our pointers, plus the callee 582 // save area that lives on the caller stack. 583 SUB $(asmcgocallSaveOffset+16), R1 584 RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI 585 MOVD R5, (asmcgocallSaveOffset+8)(R1)// save old g on stack 586 MOVD (g_stack+stack_hi)(R5), R5 587 SUB R7, R5 588 MOVD R5, asmcgocallSaveOffset(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 589 #ifdef GOOS_aix 590 MOVD R7, 0(R1) // Save frame pointer to allow manual backtrace with gdb 591 #else 592 MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?) 593 #endif 594 // This is a "global call", so put the global entry point in r12 595 MOVD R3, R12 596 597 #ifdef GOARCH_ppc64 598 // ppc64 use elf ABI v1. we must get the real entry address from 599 // first slot of the function descriptor before call. 600 // Same for AIX. 601 MOVD 8(R12), R2 602 MOVD (R12), R12 603 #endif 604 MOVD R12, CTR 605 MOVD R4, R3 // arg in r3 606 BL (CTR) 607 // C code can clobber R0, so set it back to 0. F27-F31 are 608 // callee save, so we don't need to recover those. 609 XOR R0, R0 610 // Restore g, stack pointer, toc pointer. 611 // R3 is errno, so don't touch it 612 MOVD (asmcgocallSaveOffset+8)(R1), g 613 MOVD (g_stack+stack_hi)(g), R5 614 MOVD asmcgocallSaveOffset(R1), R6 615 SUB R6, R5 616 #ifndef GOOS_aix 617 MOVD 24(R5), R2 618 #endif 619 MOVD R5, R1 620 BL runtime·save_g(SB) 621 622 MOVW R3, ret+16(FP) 623 RET 624 625 // func cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) 626 // See cgocall.go for more details. 627 TEXT ·cgocallback(SB),NOSPLIT,$24-24 628 NO_LOCAL_POINTERS 629 630 // Load m and g from thread-local storage. 631 MOVBZ runtime·iscgo(SB), R3 632 CMP R3, $0 633 BEQ nocgo 634 BL runtime·load_g(SB) 635 nocgo: 636 637 // If g is nil, Go did not create the current thread. 638 // Call needm to obtain one for temporary use. 639 // In this case, we're running on the thread stack, so there's 640 // lots of space, but the linker doesn't know. Hide the call from 641 // the linker analysis by using an indirect call. 642 CMP g, $0 643 BEQ needm 644 645 MOVD g_m(g), R8 646 MOVD R8, savedm-8(SP) 647 BR havem 648 649 needm: 650 MOVD g, savedm-8(SP) // g is zero, so is m. 651 MOVD $runtime·needm(SB), R12 652 MOVD R12, CTR 653 BL (CTR) 654 655 // Set m->sched.sp = SP, so that if a panic happens 656 // during the function we are about to execute, it will 657 // have a valid SP to run on the g0 stack. 658 // The next few lines (after the havem label) 659 // will save this SP onto the stack and then write 660 // the same SP back to m->sched.sp. That seems redundant, 661 // but if an unrecovered panic happens, unwindm will 662 // restore the g->sched.sp from the stack location 663 // and then systemstack will try to use it. If we don't set it here, 664 // that restored SP will be uninitialized (typically 0) and 665 // will not be usable. 666 MOVD g_m(g), R8 667 MOVD m_g0(R8), R3 668 MOVD R1, (g_sched+gobuf_sp)(R3) 669 670 havem: 671 // Now there's a valid m, and we're running on its m->g0. 672 // Save current m->g0->sched.sp on stack and then set it to SP. 673 // Save current sp in m->g0->sched.sp in preparation for 674 // switch back to m->curg stack. 675 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 676 MOVD m_g0(R8), R3 677 MOVD (g_sched+gobuf_sp)(R3), R4 678 MOVD R4, savedsp-24(SP) // must match frame size 679 MOVD R1, (g_sched+gobuf_sp)(R3) 680 681 // Switch to m->curg stack and call runtime.cgocallbackg. 682 // Because we are taking over the execution of m->curg 683 // but *not* resuming what had been running, we need to 684 // save that information (m->curg->sched) so we can restore it. 685 // We can restore m->curg->sched.sp easily, because calling 686 // runtime.cgocallbackg leaves SP unchanged upon return. 687 // To save m->curg->sched.pc, we push it onto the curg stack and 688 // open a frame the same size as cgocallback's g0 frame. 689 // Once we switch to the curg stack, the pushed PC will appear 690 // to be the return PC of cgocallback, so that the traceback 691 // will seamlessly trace back into the earlier calls. 692 MOVD m_curg(R8), g 693 BL runtime·save_g(SB) 694 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 695 MOVD (g_sched+gobuf_pc)(g), R5 696 MOVD R5, -(24+FIXED_FRAME)(R4) // "saved LR"; must match frame size 697 // Gather our arguments into registers. 698 MOVD fn+0(FP), R5 699 MOVD frame+8(FP), R6 700 MOVD ctxt+16(FP), R7 701 MOVD $-(24+FIXED_FRAME)(R4), R1 // switch stack; must match frame size 702 MOVD R5, FIXED_FRAME+0(R1) 703 MOVD R6, FIXED_FRAME+8(R1) 704 MOVD R7, FIXED_FRAME+16(R1) 705 706 MOVD $runtime·cgocallbackg(SB), R12 707 MOVD R12, CTR 708 CALL (CTR) // indirect call to bypass nosplit check. We're on a different stack now. 709 710 // Restore g->sched (== m->curg->sched) from saved values. 711 MOVD 0(R1), R5 712 MOVD R5, (g_sched+gobuf_pc)(g) 713 MOVD $(24+FIXED_FRAME)(R1), R4 // must match frame size 714 MOVD R4, (g_sched+gobuf_sp)(g) 715 716 // Switch back to m->g0's stack and restore m->g0->sched.sp. 717 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 718 // so we do not have to restore it.) 719 MOVD g_m(g), R8 720 MOVD m_g0(R8), g 721 BL runtime·save_g(SB) 722 MOVD (g_sched+gobuf_sp)(g), R1 723 MOVD savedsp-24(SP), R4 // must match frame size 724 MOVD R4, (g_sched+gobuf_sp)(g) 725 726 // If the m on entry was nil, we called needm above to borrow an m 727 // for the duration of the call. Since the call is over, return it with dropm. 728 MOVD savedm-8(SP), R6 729 CMP R6, $0 730 BNE droppedm 731 MOVD $runtime·dropm(SB), R12 732 MOVD R12, CTR 733 BL (CTR) 734 droppedm: 735 736 // Done! 737 RET 738 739 // void setg(G*); set g. for use by needm. 740 TEXT runtime·setg(SB), NOSPLIT, $0-8 741 MOVD gg+0(FP), g 742 // This only happens if iscgo, so jump straight to save_g 743 BL runtime·save_g(SB) 744 RET 745 746 #ifdef GOARCH_ppc64 747 #ifdef GOOS_aix 748 DATA setg_gcc<>+0(SB)/8, $_setg_gcc<>(SB) 749 DATA setg_gcc<>+8(SB)/8, $TOC(SB) 750 DATA setg_gcc<>+16(SB)/8, $0 751 GLOBL setg_gcc<>(SB), NOPTR, $24 752 #else 753 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 754 DWORD $_setg_gcc<>(SB) 755 DWORD $0 756 DWORD $0 757 #endif 758 #endif 759 760 // void setg_gcc(G*); set g in C TLS. 761 // Must obey the gcc calling convention. 762 #ifdef GOARCH_ppc64le 763 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 764 #else 765 TEXT _setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 766 #endif 767 // The standard prologue clobbers R31, which is callee-save in 768 // the C ABI, so we have to use $-8-0 and save LR ourselves. 769 MOVD LR, R4 770 // Also save g and R31, since they're callee-save in C ABI 771 MOVD R31, R5 772 MOVD g, R6 773 774 MOVD R3, g 775 BL runtime·save_g(SB) 776 777 MOVD R6, g 778 MOVD R5, R31 779 MOVD R4, LR 780 RET 781 782 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 783 MOVW (R0), R0 784 UNDEF 785 786 #define TBR 268 787 788 // int64 runtime·cputicks(void) 789 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 790 MOVD SPR(TBR), R3 791 MOVD R3, ret+0(FP) 792 RET 793 794 // spillArgs stores return values from registers to a *internal/abi.RegArgs in R20. 795 TEXT runtime·spillArgs(SB),NOSPLIT,$0-0 796 MOVD R3, 0(R20) 797 MOVD R4, 8(R20) 798 MOVD R5, 16(R20) 799 MOVD R6, 24(R20) 800 MOVD R7, 32(R20) 801 MOVD R8, 40(R20) 802 MOVD R9, 48(R20) 803 MOVD R10, 56(R20) 804 MOVD R14, 64(R20) 805 MOVD R15, 72(R20) 806 MOVD R16, 80(R20) 807 MOVD R17, 88(R20) 808 FMOVD F1, 96(R20) 809 FMOVD F2, 104(R20) 810 FMOVD F3, 112(R20) 811 FMOVD F4, 120(R20) 812 FMOVD F5, 128(R20) 813 FMOVD F6, 136(R20) 814 FMOVD F7, 144(R20) 815 FMOVD F8, 152(R20) 816 FMOVD F9, 160(R20) 817 FMOVD F10, 168(R20) 818 FMOVD F11, 176(R20) 819 FMOVD F12, 184(R20) 820 RET 821 822 // unspillArgs loads args into registers from a *internal/abi.RegArgs in R20. 823 TEXT runtime·unspillArgs(SB),NOSPLIT,$0-0 824 MOVD 0(R20), R3 825 MOVD 8(R20), R4 826 MOVD 16(R20), R5 827 MOVD 24(R20), R6 828 MOVD 32(R20), R7 829 MOVD 40(R20), R8 830 MOVD 48(R20), R9 831 MOVD 56(R20), R10 832 MOVD 64(R20), R14 833 MOVD 72(R20), R15 834 MOVD 80(R20), R16 835 MOVD 88(R20), R17 836 FMOVD 96(R20), F1 837 FMOVD 104(R20), F2 838 FMOVD 112(R20), F3 839 FMOVD 120(R20), F4 840 FMOVD 128(R20), F5 841 FMOVD 136(R20), F6 842 FMOVD 144(R20), F7 843 FMOVD 152(R20), F8 844 FMOVD 160(R20), F9 845 FMOVD 168(R20), F10 846 FMOVD 176(R20), F11 847 FMOVD 184(R20), F12 848 RET 849 850 // AES hashing not implemented for ppc64 851 TEXT runtime·memhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32 852 JMP runtime·memhashFallback<ABIInternal>(SB) 853 TEXT runtime·strhash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 854 JMP runtime·strhashFallback<ABIInternal>(SB) 855 TEXT runtime·memhash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 856 JMP runtime·memhash32Fallback<ABIInternal>(SB) 857 TEXT runtime·memhash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24 858 JMP runtime·memhash64Fallback<ABIInternal>(SB) 859 860 TEXT runtime·return0(SB), NOSPLIT, $0 861 MOVW $0, R3 862 RET 863 864 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 865 // Must obey the gcc calling convention. 866 #ifdef GOOS_aix 867 // On AIX, _cgo_topofstack is defined in runtime/cgo, because it must 868 // be a longcall in order to prevent trampolines from ld. 869 TEXT __cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 870 #else 871 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 872 #endif 873 // g (R30) and R31 are callee-save in the C ABI, so save them 874 MOVD g, R4 875 MOVD R31, R5 876 MOVD LR, R6 877 878 BL runtime·load_g(SB) // clobbers g (R30), R31 879 MOVD g_m(g), R3 880 MOVD m_curg(R3), R3 881 MOVD (g_stack+stack_hi)(R3), R3 882 883 MOVD R4, g 884 MOVD R5, R31 885 MOVD R6, LR 886 RET 887 888 // The top-most function running on a goroutine 889 // returns to goexit+PCQuantum. 890 // 891 // When dynamically linking Go, it can be returned to from a function 892 // implemented in a different module and so needs to reload the TOC pointer 893 // from the stack (although this function declares that it does not set up x-a 894 // frame, newproc1 does in fact allocate one for goexit and saves the TOC 895 // pointer in the correct place). 896 // goexit+_PCQuantum is halfway through the usual global entry point prologue 897 // that derives r2 from r12 which is a bit silly, but not harmful. 898 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 899 MOVD 24(R1), R2 900 BL runtime·goexit1(SB) // does not return 901 // traceback from goexit1 must hit code range of goexit 902 MOVD R0, R0 // NOP 903 904 // prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the 905 // module containing runtime) to the frame that goexit will execute in when 906 // the goroutine exits. It's implemented in assembly mainly because that's the 907 // easiest way to get access to R2. 908 TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8 909 MOVD sp+0(FP), R3 910 MOVD R2, 24(R3) 911 RET 912 913 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 914 ADD $-8, R1 915 MOVD R31, 0(R1) 916 MOVD runtime·lastmoduledatap(SB), R4 917 MOVD R3, moduledata_next(R4) 918 MOVD R3, runtime·lastmoduledatap(SB) 919 MOVD 0(R1), R31 920 ADD $8, R1 921 RET 922 923 TEXT ·checkASM(SB),NOSPLIT,$0-1 924 MOVW $1, R3 925 MOVB R3, ret+0(FP) 926 RET 927 928 // gcWriteBarrier performs a heap pointer write and informs the GC. 929 // 930 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 931 // - R20 is the destination of the write 932 // - R21 is the value being written at R20. 933 // It clobbers condition codes. 934 // It does not clobber R0 through R17 (except special registers), 935 // but may clobber any other register, *including* R31. 936 TEXT runtime·gcWriteBarrier<ABIInternal>(SB),NOSPLIT,$112 937 // The standard prologue clobbers R31. 938 // We use R18 and R19 as scratch registers. 939 MOVD g_m(g), R18 940 MOVD m_p(R18), R18 941 MOVD (p_wbBuf+wbBuf_next)(R18), R19 942 // Increment wbBuf.next position. 943 ADD $16, R19 944 MOVD R19, (p_wbBuf+wbBuf_next)(R18) 945 MOVD (p_wbBuf+wbBuf_end)(R18), R18 946 CMP R18, R19 947 // Record the write. 948 MOVD R21, -16(R19) // Record value 949 MOVD (R20), R18 // TODO: This turns bad writes into bad reads. 950 MOVD R18, -8(R19) // Record *slot 951 // Is the buffer full? (flags set in CMP above) 952 BEQ flush 953 ret: 954 // Do the write. 955 MOVD R21, (R20) 956 RET 957 958 flush: 959 // Save registers R0 through R15 since these were not saved by the caller. 960 // We don't save all registers on ppc64 because it takes too much space. 961 MOVD R20, (FIXED_FRAME+0)(R1) // Also first argument to wbBufFlush 962 MOVD R21, (FIXED_FRAME+8)(R1) // Also second argument to wbBufFlush 963 // R0 is always 0, so no need to spill. 964 // R1 is SP. 965 // R2 is SB. 966 MOVD R3, (FIXED_FRAME+16)(R1) 967 MOVD R4, (FIXED_FRAME+24)(R1) 968 MOVD R5, (FIXED_FRAME+32)(R1) 969 MOVD R6, (FIXED_FRAME+40)(R1) 970 MOVD R7, (FIXED_FRAME+48)(R1) 971 MOVD R8, (FIXED_FRAME+56)(R1) 972 MOVD R9, (FIXED_FRAME+64)(R1) 973 MOVD R10, (FIXED_FRAME+72)(R1) 974 // R11, R12 may be clobbered by external-linker-inserted trampoline 975 // R13 is REGTLS 976 MOVD R14, (FIXED_FRAME+80)(R1) 977 MOVD R15, (FIXED_FRAME+88)(R1) 978 MOVD R16, (FIXED_FRAME+96)(R1) 979 MOVD R17, (FIXED_FRAME+104)(R1) 980 981 // This takes arguments R20 and R21. 982 CALL runtime·wbBufFlush(SB) 983 984 MOVD (FIXED_FRAME+0)(R1), R20 985 MOVD (FIXED_FRAME+8)(R1), R21 986 MOVD (FIXED_FRAME+16)(R1), R3 987 MOVD (FIXED_FRAME+24)(R1), R4 988 MOVD (FIXED_FRAME+32)(R1), R5 989 MOVD (FIXED_FRAME+40)(R1), R6 990 MOVD (FIXED_FRAME+48)(R1), R7 991 MOVD (FIXED_FRAME+56)(R1), R8 992 MOVD (FIXED_FRAME+64)(R1), R9 993 MOVD (FIXED_FRAME+72)(R1), R10 994 MOVD (FIXED_FRAME+80)(R1), R14 995 MOVD (FIXED_FRAME+88)(R1), R15 996 MOVD (FIXED_FRAME+96)(R1), R16 997 MOVD (FIXED_FRAME+104)(R1), R17 998 JMP ret 999 1000 // Note: these functions use a special calling convention to save generated code space. 1001 // Arguments are passed in registers, but the space for those arguments are allocated 1002 // in the caller's stack frame. These stubs write the args into that stack space and 1003 // then tail call to the corresponding runtime handler. 1004 // The tail call makes these stubs disappear in backtraces. 1005 TEXT runtime·panicIndex<ABIInternal>(SB),NOSPLIT,$0-16 1006 JMP runtime·goPanicIndex<ABIInternal>(SB) 1007 TEXT runtime·panicIndexU<ABIInternal>(SB),NOSPLIT,$0-16 1008 JMP runtime·goPanicIndexU<ABIInternal>(SB) 1009 TEXT runtime·panicSliceAlen<ABIInternal>(SB),NOSPLIT,$0-16 1010 MOVD R4, R3 1011 MOVD R5, R4 1012 JMP runtime·goPanicSliceAlen<ABIInternal>(SB) 1013 TEXT runtime·panicSliceAlenU<ABIInternal>(SB),NOSPLIT,$0-16 1014 MOVD R4, R3 1015 MOVD R5, R4 1016 JMP runtime·goPanicSliceAlenU<ABIInternal>(SB) 1017 TEXT runtime·panicSliceAcap<ABIInternal>(SB),NOSPLIT,$0-16 1018 MOVD R4, R3 1019 MOVD R5, R4 1020 JMP runtime·goPanicSliceAcap<ABIInternal>(SB) 1021 TEXT runtime·panicSliceAcapU<ABIInternal>(SB),NOSPLIT,$0-16 1022 MOVD R4, R3 1023 MOVD R5, R4 1024 JMP runtime·goPanicSliceAcapU<ABIInternal>(SB) 1025 TEXT runtime·panicSliceB<ABIInternal>(SB),NOSPLIT,$0-16 1026 JMP runtime·goPanicSliceB<ABIInternal>(SB) 1027 TEXT runtime·panicSliceBU<ABIInternal>(SB),NOSPLIT,$0-16 1028 JMP runtime·goPanicSliceBU<ABIInternal>(SB) 1029 TEXT runtime·panicSlice3Alen<ABIInternal>(SB),NOSPLIT,$0-16 1030 MOVD R5, R3 1031 MOVD R6, R4 1032 JMP runtime·goPanicSlice3Alen<ABIInternal>(SB) 1033 TEXT runtime·panicSlice3AlenU<ABIInternal>(SB),NOSPLIT,$0-16 1034 MOVD R5, R3 1035 MOVD R6, R4 1036 JMP runtime·goPanicSlice3AlenU<ABIInternal>(SB) 1037 TEXT runtime·panicSlice3Acap<ABIInternal>(SB),NOSPLIT,$0-16 1038 MOVD R5, R3 1039 MOVD R6, R4 1040 JMP runtime·goPanicSlice3Acap<ABIInternal>(SB) 1041 TEXT runtime·panicSlice3AcapU<ABIInternal>(SB),NOSPLIT,$0-16 1042 MOVD R5, R3 1043 MOVD R6, R4 1044 JMP runtime·goPanicSlice3AcapU<ABIInternal>(SB) 1045 TEXT runtime·panicSlice3B<ABIInternal>(SB),NOSPLIT,$0-16 1046 MOVD R4, R3 1047 MOVD R5, R4 1048 JMP runtime·goPanicSlice3B<ABIInternal>(SB) 1049 TEXT runtime·panicSlice3BU<ABIInternal>(SB),NOSPLIT,$0-16 1050 MOVD R4, R3 1051 MOVD R5, R4 1052 JMP runtime·goPanicSlice3BU<ABIInternal>(SB) 1053 TEXT runtime·panicSlice3C<ABIInternal>(SB),NOSPLIT,$0-16 1054 JMP runtime·goPanicSlice3C<ABIInternal>(SB) 1055 TEXT runtime·panicSlice3CU<ABIInternal>(SB),NOSPLIT,$0-16 1056 JMP runtime·goPanicSlice3CU<ABIInternal>(SB) 1057 TEXT runtime·panicSliceConvert<ABIInternal>(SB),NOSPLIT,$0-16 1058 MOVD R5, R3 1059 MOVD R6, R4 1060 JMP runtime·goPanicSliceConvert<ABIInternal>(SB) 1061 1062 // These functions are used when internal linking cgo with external 1063 // objects compiled with the -Os on gcc. They reduce prologue/epilogue 1064 // size by deferring preservation of callee-save registers to a shared 1065 // function. These are defined in PPC64 ELFv2 2.3.3 (but also present 1066 // in ELFv1) 1067 // 1068 // These appear unused, but the linker will redirect calls to functions 1069 // like _savegpr0_14 or _restgpr1_14 to runtime.elf_savegpr0 or 1070 // runtime.elf_restgpr1 with an appropriate offset based on the number 1071 // register operations required when linking external objects which 1072 // make these calls. For GPR/FPR saves, the minimum register value is 1073 // 14, for VR it is 20. 1074 // 1075 // These are only used when linking such cgo code internally. Note, R12 1076 // and R0 may be used in different ways than regular ELF compliant 1077 // functions. 1078 TEXT runtime·elf_savegpr0(SB),NOSPLIT|NOFRAME,$0 1079 // R0 holds the LR of the caller's caller, R1 holds save location 1080 MOVD R14, -144(R1) 1081 MOVD R15, -136(R1) 1082 MOVD R16, -128(R1) 1083 MOVD R17, -120(R1) 1084 MOVD R18, -112(R1) 1085 MOVD R19, -104(R1) 1086 MOVD R20, -96(R1) 1087 MOVD R21, -88(R1) 1088 MOVD R22, -80(R1) 1089 MOVD R23, -72(R1) 1090 MOVD R24, -64(R1) 1091 MOVD R25, -56(R1) 1092 MOVD R26, -48(R1) 1093 MOVD R27, -40(R1) 1094 MOVD R28, -32(R1) 1095 MOVD R29, -24(R1) 1096 MOVD g, -16(R1) 1097 MOVD R31, -8(R1) 1098 MOVD R0, 16(R1) 1099 RET 1100 TEXT runtime·elf_restgpr0(SB),NOSPLIT|NOFRAME,$0 1101 // R1 holds save location. This returns to the LR saved on stack (bypassing the caller) 1102 MOVD -144(R1), R14 1103 MOVD -136(R1), R15 1104 MOVD -128(R1), R16 1105 MOVD -120(R1), R17 1106 MOVD -112(R1), R18 1107 MOVD -104(R1), R19 1108 MOVD -96(R1), R20 1109 MOVD -88(R1), R21 1110 MOVD -80(R1), R22 1111 MOVD -72(R1), R23 1112 MOVD -64(R1), R24 1113 MOVD -56(R1), R25 1114 MOVD -48(R1), R26 1115 MOVD -40(R1), R27 1116 MOVD -32(R1), R28 1117 MOVD -24(R1), R29 1118 MOVD -16(R1), g 1119 MOVD -8(R1), R31 1120 MOVD 16(R1), R0 // Load and return to saved LR 1121 MOVD R0, LR 1122 RET 1123 TEXT runtime·elf_savegpr1(SB),NOSPLIT|NOFRAME,$0 1124 // R12 holds the save location 1125 MOVD R14, -144(R12) 1126 MOVD R15, -136(R12) 1127 MOVD R16, -128(R12) 1128 MOVD R17, -120(R12) 1129 MOVD R18, -112(R12) 1130 MOVD R19, -104(R12) 1131 MOVD R20, -96(R12) 1132 MOVD R21, -88(R12) 1133 MOVD R22, -80(R12) 1134 MOVD R23, -72(R12) 1135 MOVD R24, -64(R12) 1136 MOVD R25, -56(R12) 1137 MOVD R26, -48(R12) 1138 MOVD R27, -40(R12) 1139 MOVD R28, -32(R12) 1140 MOVD R29, -24(R12) 1141 MOVD g, -16(R12) 1142 MOVD R31, -8(R12) 1143 RET 1144 TEXT runtime·elf_restgpr1(SB),NOSPLIT|NOFRAME,$0 1145 // R12 holds the save location 1146 MOVD -144(R12), R14 1147 MOVD -136(R12), R15 1148 MOVD -128(R12), R16 1149 MOVD -120(R12), R17 1150 MOVD -112(R12), R18 1151 MOVD -104(R12), R19 1152 MOVD -96(R12), R20 1153 MOVD -88(R12), R21 1154 MOVD -80(R12), R22 1155 MOVD -72(R12), R23 1156 MOVD -64(R12), R24 1157 MOVD -56(R12), R25 1158 MOVD -48(R12), R26 1159 MOVD -40(R12), R27 1160 MOVD -32(R12), R28 1161 MOVD -24(R12), R29 1162 MOVD -16(R12), g 1163 MOVD -8(R12), R31 1164 RET 1165 TEXT runtime·elf_savefpr(SB),NOSPLIT|NOFRAME,$0 1166 // R0 holds the LR of the caller's caller, R1 holds save location 1167 FMOVD F14, -144(R1) 1168 FMOVD F15, -136(R1) 1169 FMOVD F16, -128(R1) 1170 FMOVD F17, -120(R1) 1171 FMOVD F18, -112(R1) 1172 FMOVD F19, -104(R1) 1173 FMOVD F20, -96(R1) 1174 FMOVD F21, -88(R1) 1175 FMOVD F22, -80(R1) 1176 FMOVD F23, -72(R1) 1177 FMOVD F24, -64(R1) 1178 FMOVD F25, -56(R1) 1179 FMOVD F26, -48(R1) 1180 FMOVD F27, -40(R1) 1181 FMOVD F28, -32(R1) 1182 FMOVD F29, -24(R1) 1183 FMOVD F30, -16(R1) 1184 FMOVD F31, -8(R1) 1185 MOVD R0, 16(R1) 1186 RET 1187 TEXT runtime·elf_restfpr(SB),NOSPLIT|NOFRAME,$0 1188 // R1 holds save location. This returns to the LR saved on stack (bypassing the caller) 1189 FMOVD -144(R1), F14 1190 FMOVD -136(R1), F15 1191 FMOVD -128(R1), F16 1192 FMOVD -120(R1), F17 1193 FMOVD -112(R1), F18 1194 FMOVD -104(R1), F19 1195 FMOVD -96(R1), F20 1196 FMOVD -88(R1), F21 1197 FMOVD -80(R1), F22 1198 FMOVD -72(R1), F23 1199 FMOVD -64(R1), F24 1200 FMOVD -56(R1), F25 1201 FMOVD -48(R1), F26 1202 FMOVD -40(R1), F27 1203 FMOVD -32(R1), F28 1204 FMOVD -24(R1), F29 1205 FMOVD -16(R1), F30 1206 FMOVD -8(R1), F31 1207 MOVD 16(R1), R0 // Load and return to saved LR 1208 MOVD R0, LR 1209 RET 1210 TEXT runtime·elf_savevr(SB),NOSPLIT|NOFRAME,$0 1211 // R0 holds the save location, R12 is clobbered 1212 MOVD $-192, R12 1213 STVX V20, (R0+R12) 1214 MOVD $-176, R12 1215 STVX V21, (R0+R12) 1216 MOVD $-160, R12 1217 STVX V22, (R0+R12) 1218 MOVD $-144, R12 1219 STVX V23, (R0+R12) 1220 MOVD $-128, R12 1221 STVX V24, (R0+R12) 1222 MOVD $-112, R12 1223 STVX V25, (R0+R12) 1224 MOVD $-96, R12 1225 STVX V26, (R0+R12) 1226 MOVD $-80, R12 1227 STVX V27, (R0+R12) 1228 MOVD $-64, R12 1229 STVX V28, (R0+R12) 1230 MOVD $-48, R12 1231 STVX V29, (R0+R12) 1232 MOVD $-32, R12 1233 STVX V30, (R0+R12) 1234 MOVD $-16, R12 1235 STVX V31, (R0+R12) 1236 RET 1237 TEXT runtime·elf_restvr(SB),NOSPLIT|NOFRAME,$0 1238 // R0 holds the save location, R12 is clobbered 1239 MOVD $-192, R12 1240 LVX (R0+R12), V20 1241 MOVD $-176, R12 1242 LVX (R0+R12), V21 1243 MOVD $-160, R12 1244 LVX (R0+R12), V22 1245 MOVD $-144, R12 1246 LVX (R0+R12), V23 1247 MOVD $-128, R12 1248 LVX (R0+R12), V24 1249 MOVD $-112, R12 1250 LVX (R0+R12), V25 1251 MOVD $-96, R12 1252 LVX (R0+R12), V26 1253 MOVD $-80, R12 1254 LVX (R0+R12), V27 1255 MOVD $-64, R12 1256 LVX (R0+R12), V28 1257 MOVD $-48, R12 1258 LVX (R0+R12), V29 1259 MOVD $-32, R12 1260 LVX (R0+R12), V30 1261 MOVD $-16, R12 1262 LVX (R0+R12), V31 1263 RET