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