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