1// Copyright 2014 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5// +build ppc64 ppc64le 6 7#include "go_asm.h" 8#include "go_tls.h" 9#include "funcdata.h" 10#include "textflag.h" 11#include "asm_ppc64x.h" 12 13TEXT runtime·rt0_go(SB),NOSPLIT,$0 14 // R1 = stack; R3 = argc; R4 = argv; R13 = C TLS base pointer 15 16 // initialize essential registers 17 BL runtime·reginit(SB) 18 19 SUB $(FIXED_FRAME+16), R1 20 MOVD R2, 24(R1) // stash the TOC pointer away again now we've created a new frame 21 MOVW R3, FIXED_FRAME+0(R1) // argc 22 MOVD R4, FIXED_FRAME+8(R1) // argv 23 24 // create istack out of the given (operating system) stack. 25 // _cgo_init may update stackguard. 26 MOVD $runtime·g0(SB), g 27 MOVD $(-64*1024), R31 28 ADD R31, R1, R3 29 MOVD R3, g_stackguard0(g) 30 MOVD R3, g_stackguard1(g) 31 MOVD R3, (g_stack+stack_lo)(g) 32 MOVD R1, (g_stack+stack_hi)(g) 33 34 // if there is a _cgo_init, call it using the gcc ABI. 35 MOVD _cgo_init(SB), R12 36 CMP R0, R12 37 BEQ nocgo 38 MOVD R12, CTR // r12 = "global function entry point" 39 MOVD R13, R5 // arg 2: TLS base pointer 40 MOVD $setg_gcc<>(SB), R4 // arg 1: setg 41 MOVD g, R3 // arg 0: G 42 // C functions expect 32 bytes of space on caller stack frame 43 // and a 16-byte aligned R1 44 MOVD R1, R14 // save current stack 45 SUB $32, R1 // reserve 32 bytes 46 RLDCR $0, R1, $~15, R1 // 16-byte align 47 BL (CTR) // may clobber R0, R3-R12 48 MOVD R14, R1 // restore stack 49 MOVD 24(R1), R2 50 XOR R0, R0 // fix R0 51 52nocgo: 53 // update stackguard after _cgo_init 54 MOVD (g_stack+stack_lo)(g), R3 55 ADD $const__StackGuard, R3 56 MOVD R3, g_stackguard0(g) 57 MOVD R3, g_stackguard1(g) 58 59 // set the per-goroutine and per-mach "registers" 60 MOVD $runtime·m0(SB), R3 61 62 // save m->g0 = g0 63 MOVD g, m_g0(R3) 64 // save m0 to g0->m 65 MOVD R3, g_m(g) 66 67 BL runtime·check(SB) 68 69 // args are already prepared 70 BL runtime·args(SB) 71 BL runtime·osinit(SB) 72 BL runtime·schedinit(SB) 73 74 // create a new goroutine to start program 75 MOVD $runtime·mainPC(SB), R3 // entry 76 MOVDU R3, -8(R1) 77 MOVDU R0, -8(R1) 78 MOVDU R0, -8(R1) 79 MOVDU R0, -8(R1) 80 MOVDU R0, -8(R1) 81 MOVDU R0, -8(R1) 82 BL runtime·newproc(SB) 83 ADD $(16+FIXED_FRAME), R1 84 85 // start this M 86 BL runtime·mstart(SB) 87 88 MOVD R0, 1(R0) 89 RET 90 91DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 92GLOBL runtime·mainPC(SB),RODATA,$8 93 94TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 95 MOVD R0, 2(R0) // TODO: TD 96 RET 97 98TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 99 RET 100 101TEXT _cgo_reginit(SB),NOSPLIT|NOFRAME,$0-0 102 // crosscall_ppc64 and crosscall2 need to reginit, but can't 103 // get at the 'runtime.reginit' symbol. 104 BR runtime·reginit(SB) 105 106TEXT runtime·reginit(SB),NOSPLIT|NOFRAME,$0-0 107 // set R0 to zero, it's expected by the toolchain 108 XOR R0, R0 109 RET 110 111/* 112 * go-routine 113 */ 114 115// void gosave(Gobuf*) 116// save state in Gobuf; setjmp 117TEXT runtime·gosave(SB), NOSPLIT|NOFRAME, $0-8 118 MOVD buf+0(FP), R3 119 MOVD R1, gobuf_sp(R3) 120 MOVD LR, R31 121 MOVD R31, gobuf_pc(R3) 122 MOVD g, gobuf_g(R3) 123 MOVD R0, gobuf_lr(R3) 124 MOVD R0, gobuf_ret(R3) 125 // Assert ctxt is zero. See func save. 126 MOVD gobuf_ctxt(R3), R3 127 CMP R0, R3 128 BEQ 2(PC) 129 BL runtime·badctxt(SB) 130 RET 131 132// void gogo(Gobuf*) 133// restore state from Gobuf; longjmp 134TEXT runtime·gogo(SB), NOSPLIT, $16-8 135 MOVD buf+0(FP), R5 136 137 // If ctxt is not nil, invoke deletion barrier before overwriting. 138 MOVD gobuf_ctxt(R5), R3 139 CMP R0, R3 140 BEQ nilctxt 141 MOVD $gobuf_ctxt(R5), R3 142 MOVD R3, FIXED_FRAME+0(R1) 143 MOVD R0, FIXED_FRAME+8(R1) 144 BL runtime·writebarrierptr_prewrite(SB) 145 MOVD buf+0(FP), R5 146 147nilctxt: 148 MOVD gobuf_g(R5), g // make sure g is not nil 149 BL runtime·save_g(SB) 150 151 MOVD 0(g), R4 152 MOVD gobuf_sp(R5), R1 153 MOVD gobuf_lr(R5), R31 154 MOVD R31, LR 155 MOVD gobuf_ret(R5), R3 156 MOVD gobuf_ctxt(R5), R11 157 MOVD R0, gobuf_sp(R5) 158 MOVD R0, gobuf_ret(R5) 159 MOVD R0, gobuf_lr(R5) 160 MOVD R0, gobuf_ctxt(R5) 161 CMP R0, R0 // set condition codes for == test, needed by stack split 162 MOVD gobuf_pc(R5), R12 163 MOVD R12, CTR 164 BR (CTR) 165 166// void mcall(fn func(*g)) 167// Switch to m->g0's stack, call fn(g). 168// Fn must never return. It should gogo(&g->sched) 169// to keep running g. 170TEXT runtime·mcall(SB), NOSPLIT|NOFRAME, $0-8 171 // Save caller state in g->sched 172 MOVD R1, (g_sched+gobuf_sp)(g) 173 MOVD LR, R31 174 MOVD R31, (g_sched+gobuf_pc)(g) 175 MOVD R0, (g_sched+gobuf_lr)(g) 176 MOVD g, (g_sched+gobuf_g)(g) 177 178 // Switch to m->g0 & its stack, call fn. 179 MOVD g, R3 180 MOVD g_m(g), R8 181 MOVD m_g0(R8), g 182 BL runtime·save_g(SB) 183 CMP g, R3 184 BNE 2(PC) 185 BR runtime·badmcall(SB) 186 MOVD fn+0(FP), R11 // context 187 MOVD 0(R11), R12 // code pointer 188 MOVD R12, CTR 189 MOVD (g_sched+gobuf_sp)(g), R1 // sp = m->g0->sched.sp 190 MOVDU R3, -8(R1) 191 MOVDU R0, -8(R1) 192 MOVDU R0, -8(R1) 193 MOVDU R0, -8(R1) 194 MOVDU R0, -8(R1) 195 BL (CTR) 196 MOVD 24(R1), R2 197 BR runtime·badmcall2(SB) 198 199// systemstack_switch is a dummy routine that systemstack leaves at the bottom 200// of the G stack. We need to distinguish the routine that 201// lives at the bottom of the G stack from the one that lives 202// at the top of the system stack because the one at the top of 203// the system stack terminates the stack walk (see topofstack()). 204TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 205 // We have several undefs here so that 16 bytes past 206 // $runtime·systemstack_switch lies within them whether or not the 207 // instructions that derive r2 from r12 are there. 208 UNDEF 209 UNDEF 210 UNDEF 211 BL (LR) // make sure this function is not leaf 212 RET 213 214// func systemstack(fn func()) 215TEXT runtime·systemstack(SB), NOSPLIT, $0-8 216 MOVD fn+0(FP), R3 // R3 = fn 217 MOVD R3, R11 // context 218 MOVD g_m(g), R4 // R4 = m 219 220 MOVD m_gsignal(R4), R5 // R5 = gsignal 221 CMP g, R5 222 BEQ noswitch 223 224 MOVD m_g0(R4), R5 // R5 = g0 225 CMP g, R5 226 BEQ noswitch 227 228 MOVD m_curg(R4), R6 229 CMP g, R6 230 BEQ switch 231 232 // Bad: g is not gsignal, not g0, not curg. What is it? 233 // Hide call from linker nosplit analysis. 234 MOVD $runtime·badsystemstack(SB), R12 235 MOVD R12, CTR 236 BL (CTR) 237 238switch: 239 // save our state in g->sched. Pretend to 240 // be systemstack_switch if the G stack is scanned. 241 MOVD $runtime·systemstack_switch(SB), R6 242 ADD $16, R6 // get past prologue (including r2-setting instructions when they're there) 243 MOVD R6, (g_sched+gobuf_pc)(g) 244 MOVD R1, (g_sched+gobuf_sp)(g) 245 MOVD R0, (g_sched+gobuf_lr)(g) 246 MOVD g, (g_sched+gobuf_g)(g) 247 248 // switch to g0 249 MOVD R5, g 250 BL runtime·save_g(SB) 251 MOVD (g_sched+gobuf_sp)(g), R3 252 // make it look like mstart called systemstack on g0, to stop traceback 253 SUB $FIXED_FRAME, R3 254 MOVD $runtime·mstart(SB), R4 255 MOVD R4, 0(R3) 256 MOVD R3, R1 257 258 // call target function 259 MOVD 0(R11), R12 // code pointer 260 MOVD R12, CTR 261 BL (CTR) 262 263 // restore TOC pointer. It seems unlikely that we will use systemstack 264 // to call a function defined in another module, but the results of 265 // doing so would be so confusing that it's worth doing this. 266 MOVD g_m(g), R3 267 MOVD m_curg(R3), g 268 MOVD (g_sched+gobuf_sp)(g), R3 269 MOVD 24(R3), R2 270 // switch back to g 271 MOVD g_m(g), R3 272 MOVD m_curg(R3), g 273 BL runtime·save_g(SB) 274 MOVD (g_sched+gobuf_sp)(g), R1 275 MOVD R0, (g_sched+gobuf_sp)(g) 276 RET 277 278noswitch: 279 // already on m stack, just call directly 280 MOVD 0(R11), R12 // code pointer 281 MOVD R12, CTR 282 BL (CTR) 283 MOVD 24(R1), R2 284 RET 285 286/* 287 * support for morestack 288 */ 289 290// Called during function prolog when more stack is needed. 291// Caller has already loaded: 292// R3: framesize, R4: argsize, R5: LR 293// 294// The traceback routines see morestack on a g0 as being 295// the top of a stack (for example, morestack calling newstack 296// calling the scheduler calling newm calling gc), so we must 297// record an argument size. For that purpose, it has no arguments. 298TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 299 // Cannot grow scheduler stack (m->g0). 300 MOVD g_m(g), R7 301 MOVD m_g0(R7), R8 302 CMP g, R8 303 BNE 3(PC) 304 BL runtime·badmorestackg0(SB) 305 BL runtime·abort(SB) 306 307 // Cannot grow signal stack (m->gsignal). 308 MOVD m_gsignal(R7), R8 309 CMP g, R8 310 BNE 3(PC) 311 BL runtime·badmorestackgsignal(SB) 312 BL runtime·abort(SB) 313 314 // Called from f. 315 // Set g->sched to context in f. 316 MOVD R1, (g_sched+gobuf_sp)(g) 317 MOVD LR, R8 318 MOVD R8, (g_sched+gobuf_pc)(g) 319 MOVD R5, (g_sched+gobuf_lr)(g) 320 // newstack will fill gobuf.ctxt. 321 322 // Called from f. 323 // Set m->morebuf to f's caller. 324 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 325 MOVD R1, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 326 MOVD g, (m_morebuf+gobuf_g)(R7) 327 328 // Call newstack on m->g0's stack. 329 MOVD m_g0(R7), g 330 BL runtime·save_g(SB) 331 MOVD (g_sched+gobuf_sp)(g), R1 332 MOVDU R0, -(FIXED_FRAME+8)(R1) // create a call frame on g0 333 MOVD R11, FIXED_FRAME+0(R1) // ctxt argument 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 340TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 341 MOVD R0, R11 342 BR runtime·morestack(SB) 343 344TEXT runtime·stackBarrier(SB),NOSPLIT,$0 345 // We came here via a RET to an overwritten LR. 346 // R3 may be live. Other registers are available. 347 348 // Get the original return PC, g.stkbar[g.stkbarPos].savedLRVal. 349 MOVD (g_stkbar+slice_array)(g), R4 350 MOVD g_stkbarPos(g), R5 351 MOVD $stkbar__size, R6 352 MULLD R5, R6 353 ADD R4, R6 354 MOVD stkbar_savedLRVal(R6), R6 355 // Record that this stack barrier was hit. 356 ADD $1, R5 357 MOVD R5, g_stkbarPos(g) 358 // Jump to the original return PC. 359 MOVD R6, CTR 360 BR (CTR) 361 362// reflectcall: call a function with the given argument list 363// func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 364// we don't have variable-sized frames, so we use a small number 365// of constant-sized-frame functions to encode a few bits of size in the pc. 366// Caution: ugly multiline assembly macros in your future! 367 368#define DISPATCH(NAME,MAXSIZE) \ 369 MOVD $MAXSIZE, R31; \ 370 CMP R3, R31; \ 371 BGT 4(PC); \ 372 MOVD $NAME(SB), R12; \ 373 MOVD R12, CTR; \ 374 BR (CTR) 375// Note: can't just "BR NAME(SB)" - bad inlining results. 376 377TEXT reflect·call(SB), NOSPLIT, $0-0 378 BR ·reflectcall(SB) 379 380TEXT ·reflectcall(SB), NOSPLIT|NOFRAME, $0-32 381 MOVWZ argsize+24(FP), R3 382 DISPATCH(runtime·call32, 32) 383 DISPATCH(runtime·call64, 64) 384 DISPATCH(runtime·call128, 128) 385 DISPATCH(runtime·call256, 256) 386 DISPATCH(runtime·call512, 512) 387 DISPATCH(runtime·call1024, 1024) 388 DISPATCH(runtime·call2048, 2048) 389 DISPATCH(runtime·call4096, 4096) 390 DISPATCH(runtime·call8192, 8192) 391 DISPATCH(runtime·call16384, 16384) 392 DISPATCH(runtime·call32768, 32768) 393 DISPATCH(runtime·call65536, 65536) 394 DISPATCH(runtime·call131072, 131072) 395 DISPATCH(runtime·call262144, 262144) 396 DISPATCH(runtime·call524288, 524288) 397 DISPATCH(runtime·call1048576, 1048576) 398 DISPATCH(runtime·call2097152, 2097152) 399 DISPATCH(runtime·call4194304, 4194304) 400 DISPATCH(runtime·call8388608, 8388608) 401 DISPATCH(runtime·call16777216, 16777216) 402 DISPATCH(runtime·call33554432, 33554432) 403 DISPATCH(runtime·call67108864, 67108864) 404 DISPATCH(runtime·call134217728, 134217728) 405 DISPATCH(runtime·call268435456, 268435456) 406 DISPATCH(runtime·call536870912, 536870912) 407 DISPATCH(runtime·call1073741824, 1073741824) 408 MOVD $runtime·badreflectcall(SB), R12 409 MOVD R12, CTR 410 BR (CTR) 411 412#define CALLFN(NAME,MAXSIZE) \ 413TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 414 NO_LOCAL_POINTERS; \ 415 /* copy arguments to stack */ \ 416 MOVD arg+16(FP), R3; \ 417 MOVWZ argsize+24(FP), R4; \ 418 MOVD R1, R5; \ 419 ADD $(FIXED_FRAME-1), R5; \ 420 SUB $1, R3; \ 421 ADD R5, R4; \ 422 CMP R5, R4; \ 423 BEQ 4(PC); \ 424 MOVBZU 1(R3), R6; \ 425 MOVBZU R6, 1(R5); \ 426 BR -4(PC); \ 427 /* call function */ \ 428 MOVD f+8(FP), R11; \ 429 MOVD (R11), R12; \ 430 MOVD R12, CTR; \ 431 PCDATA $PCDATA_StackMapIndex, $0; \ 432 BL (CTR); \ 433 MOVD 24(R1), R2; \ 434 /* copy return values back */ \ 435 MOVD argtype+0(FP), R7; \ 436 MOVD arg+16(FP), R3; \ 437 MOVWZ n+24(FP), R4; \ 438 MOVWZ retoffset+28(FP), R6; \ 439 ADD $FIXED_FRAME, R1, R5; \ 440 ADD R6, R5; \ 441 ADD R6, R3; \ 442 SUB R6, R4; \ 443 BL callRet<>(SB); \ 444 RET 445 446// callRet copies return values back at the end of call*. This is a 447// separate function so it can allocate stack space for the arguments 448// to reflectcallmove. It does not follow the Go ABI; it expects its 449// arguments in registers. 450TEXT callRet<>(SB), NOSPLIT, $32-0 451 MOVD R7, FIXED_FRAME+0(R1) 452 MOVD R3, FIXED_FRAME+8(R1) 453 MOVD R5, FIXED_FRAME+16(R1) 454 MOVD R4, FIXED_FRAME+24(R1) 455 BL runtime·reflectcallmove(SB) 456 RET 457 458CALLFN(·call32, 32) 459CALLFN(·call64, 64) 460CALLFN(·call128, 128) 461CALLFN(·call256, 256) 462CALLFN(·call512, 512) 463CALLFN(·call1024, 1024) 464CALLFN(·call2048, 2048) 465CALLFN(·call4096, 4096) 466CALLFN(·call8192, 8192) 467CALLFN(·call16384, 16384) 468CALLFN(·call32768, 32768) 469CALLFN(·call65536, 65536) 470CALLFN(·call131072, 131072) 471CALLFN(·call262144, 262144) 472CALLFN(·call524288, 524288) 473CALLFN(·call1048576, 1048576) 474CALLFN(·call2097152, 2097152) 475CALLFN(·call4194304, 4194304) 476CALLFN(·call8388608, 8388608) 477CALLFN(·call16777216, 16777216) 478CALLFN(·call33554432, 33554432) 479CALLFN(·call67108864, 67108864) 480CALLFN(·call134217728, 134217728) 481CALLFN(·call268435456, 268435456) 482CALLFN(·call536870912, 536870912) 483CALLFN(·call1073741824, 1073741824) 484 485TEXT runtime·procyield(SB),NOSPLIT,$0-0 486 RET 487 488// void jmpdefer(fv, sp); 489// called from deferreturn. 490// 1. grab stored LR for caller 491// 2. sub 8 bytes to get back to either nop or toc reload before deferreturn 492// 3. BR to fn 493// When dynamically linking Go, it is not sufficient to rewind to the BL 494// deferreturn -- we might be jumping between modules and so we need to reset 495// the TOC pointer in r2. To do this, codegen inserts MOVD 24(R1), R2 *before* 496// the BL deferreturn and jmpdefer rewinds to that. 497TEXT runtime·jmpdefer(SB), NOSPLIT|NOFRAME, $0-16 498 MOVD 0(R1), R31 499 SUB $8, R31 500 MOVD R31, LR 501 502 MOVD fv+0(FP), R11 503 MOVD argp+8(FP), R1 504 SUB $FIXED_FRAME, R1 505 MOVD 0(R11), R12 506 MOVD R12, CTR 507 BR (CTR) 508 509// Save state of caller into g->sched. Smashes R31. 510TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 511 MOVD LR, R31 512 MOVD R31, (g_sched+gobuf_pc)(g) 513 MOVD R1, (g_sched+gobuf_sp)(g) 514 MOVD R0, (g_sched+gobuf_lr)(g) 515 MOVD R0, (g_sched+gobuf_ret)(g) 516 // Assert ctxt is zero. See func save. 517 MOVD (g_sched+gobuf_ctxt)(g), R31 518 CMP R0, R31 519 BEQ 2(PC) 520 BL runtime·badctxt(SB) 521 RET 522 523// func asmcgocall(fn, arg unsafe.Pointer) int32 524// Call fn(arg) on the scheduler stack, 525// aligned appropriately for the gcc ABI. 526// See cgocall.go for more details. 527TEXT ·asmcgocall(SB),NOSPLIT,$0-20 528 MOVD fn+0(FP), R3 529 MOVD arg+8(FP), R4 530 531 MOVD R1, R7 // save original stack pointer 532 MOVD g, R5 533 534 // Figure out if we need to switch to m->g0 stack. 535 // We get called to create new OS threads too, and those 536 // come in on the m->g0 stack already. 537 MOVD g_m(g), R6 538 MOVD m_g0(R6), R6 539 CMP R6, g 540 BEQ g0 541 BL gosave<>(SB) 542 MOVD R6, g 543 BL runtime·save_g(SB) 544 MOVD (g_sched+gobuf_sp)(g), R1 545 546 // Now on a scheduling stack (a pthread-created stack). 547g0: 548 // Save room for two of our pointers, plus 32 bytes of callee 549 // save area that lives on the caller stack. 550 SUB $48, R1 551 RLDCR $0, R1, $~15, R1 // 16-byte alignment for gcc ABI 552 MOVD R5, 40(R1) // save old g on stack 553 MOVD (g_stack+stack_hi)(R5), R5 554 SUB R7, R5 555 MOVD R5, 32(R1) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 556 MOVD R0, 0(R1) // clear back chain pointer (TODO can we give it real back trace information?) 557 // This is a "global call", so put the global entry point in r12 558 MOVD R3, R12 559 MOVD R12, CTR 560 MOVD R4, R3 // arg in r3 561 BL (CTR) 562 563 // C code can clobber R0, so set it back to 0. F27-F31 are 564 // callee save, so we don't need to recover those. 565 XOR R0, R0 566 // Restore g, stack pointer, toc pointer. 567 // R3 is errno, so don't touch it 568 MOVD 40(R1), g 569 MOVD (g_stack+stack_hi)(g), R5 570 MOVD 32(R1), R6 571 SUB R6, R5 572 MOVD 24(R5), R2 573 BL runtime·save_g(SB) 574 MOVD (g_stack+stack_hi)(g), R5 575 MOVD 32(R1), R6 576 SUB R6, R5 577 MOVD R5, R1 578 579 MOVW R3, ret+16(FP) 580 RET 581 582// cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 583// Turn the fn into a Go func (by taking its address) and call 584// cgocallback_gofunc. 585TEXT runtime·cgocallback(SB),NOSPLIT,$32-32 586 MOVD $fn+0(FP), R3 587 MOVD R3, FIXED_FRAME+0(R1) 588 MOVD frame+8(FP), R3 589 MOVD R3, FIXED_FRAME+8(R1) 590 MOVD framesize+16(FP), R3 591 MOVD R3, FIXED_FRAME+16(R1) 592 MOVD ctxt+24(FP), R3 593 MOVD R3, FIXED_FRAME+24(R1) 594 MOVD $runtime·cgocallback_gofunc(SB), R12 595 MOVD R12, CTR 596 BL (CTR) 597 RET 598 599// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 600// See cgocall.go for more details. 601TEXT ·cgocallback_gofunc(SB),NOSPLIT,$16-32 602 NO_LOCAL_POINTERS 603 604 // Load m and g from thread-local storage. 605 MOVB runtime·iscgo(SB), R3 606 CMP R3, $0 607 BEQ nocgo 608 BL runtime·load_g(SB) 609nocgo: 610 611 // If g is nil, Go did not create the current thread. 612 // Call needm to obtain one for temporary use. 613 // In this case, we're running on the thread stack, so there's 614 // lots of space, but the linker doesn't know. Hide the call from 615 // the linker analysis by using an indirect call. 616 CMP g, $0 617 BEQ needm 618 619 MOVD g_m(g), R8 620 MOVD R8, savedm-8(SP) 621 BR havem 622 623needm: 624 MOVD g, savedm-8(SP) // g is zero, so is m. 625 MOVD $runtime·needm(SB), R12 626 MOVD R12, CTR 627 BL (CTR) 628 629 // Set m->sched.sp = SP, so that if a panic happens 630 // during the function we are about to execute, it will 631 // have a valid SP to run on the g0 stack. 632 // The next few lines (after the havem label) 633 // will save this SP onto the stack and then write 634 // the same SP back to m->sched.sp. That seems redundant, 635 // but if an unrecovered panic happens, unwindm will 636 // restore the g->sched.sp from the stack location 637 // and then systemstack will try to use it. If we don't set it here, 638 // that restored SP will be uninitialized (typically 0) and 639 // will not be usable. 640 MOVD g_m(g), R8 641 MOVD m_g0(R8), R3 642 MOVD R1, (g_sched+gobuf_sp)(R3) 643 644havem: 645 // Now there's a valid m, and we're running on its m->g0. 646 // Save current m->g0->sched.sp on stack and then set it to SP. 647 // Save current sp in m->g0->sched.sp in preparation for 648 // switch back to m->curg stack. 649 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 650 MOVD m_g0(R8), R3 651 MOVD (g_sched+gobuf_sp)(R3), R4 652 MOVD R4, savedsp-16(SP) 653 MOVD R1, (g_sched+gobuf_sp)(R3) 654 655 // Switch to m->curg stack and call runtime.cgocallbackg. 656 // Because we are taking over the execution of m->curg 657 // but *not* resuming what had been running, we need to 658 // save that information (m->curg->sched) so we can restore it. 659 // We can restore m->curg->sched.sp easily, because calling 660 // runtime.cgocallbackg leaves SP unchanged upon return. 661 // To save m->curg->sched.pc, we push it onto the stack. 662 // This has the added benefit that it looks to the traceback 663 // routine like cgocallbackg is going to return to that 664 // PC (because the frame we allocate below has the same 665 // size as cgocallback_gofunc's frame declared above) 666 // so that the traceback will seamlessly trace back into 667 // the earlier calls. 668 // 669 // In the new goroutine, -8(SP) is unused (where SP refers to 670 // m->curg's SP while we're setting it up, before we've adjusted it). 671 MOVD m_curg(R8), g 672 BL runtime·save_g(SB) 673 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 674 MOVD (g_sched+gobuf_pc)(g), R5 675 MOVD R5, -(FIXED_FRAME+16)(R4) 676 MOVD ctxt+24(FP), R3 677 MOVD R3, -16(R4) 678 MOVD $-(FIXED_FRAME+16)(R4), R1 679 BL runtime·cgocallbackg(SB) 680 681 // Restore g->sched (== m->curg->sched) from saved values. 682 MOVD 0(R1), R5 683 MOVD R5, (g_sched+gobuf_pc)(g) 684 MOVD $(FIXED_FRAME+16)(R1), R4 685 MOVD R4, (g_sched+gobuf_sp)(g) 686 687 // Switch back to m->g0's stack and restore m->g0->sched.sp. 688 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 689 // so we do not have to restore it.) 690 MOVD g_m(g), R8 691 MOVD m_g0(R8), g 692 BL runtime·save_g(SB) 693 MOVD (g_sched+gobuf_sp)(g), R1 694 MOVD savedsp-16(SP), R4 695 MOVD R4, (g_sched+gobuf_sp)(g) 696 697 // If the m on entry was nil, we called needm above to borrow an m 698 // for the duration of the call. Since the call is over, return it with dropm. 699 MOVD savedm-8(SP), R6 700 CMP R6, $0 701 BNE droppedm 702 MOVD $runtime·dropm(SB), R12 703 MOVD R12, CTR 704 BL (CTR) 705droppedm: 706 707 // Done! 708 RET 709 710// void setg(G*); set g. for use by needm. 711TEXT runtime·setg(SB), NOSPLIT, $0-8 712 MOVD gg+0(FP), g 713 // This only happens if iscgo, so jump straight to save_g 714 BL runtime·save_g(SB) 715 RET 716 717// void setg_gcc(G*); set g in C TLS. 718// Must obey the gcc calling convention. 719TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 720 // The standard prologue clobbers R31, which is callee-save in 721 // the C ABI, so we have to use $-8-0 and save LR ourselves. 722 MOVD LR, R4 723 // Also save g and R31, since they're callee-save in C ABI 724 MOVD R31, R5 725 MOVD g, R6 726 727 MOVD R3, g 728 BL runtime·save_g(SB) 729 730 MOVD R6, g 731 MOVD R5, R31 732 MOVD R4, LR 733 RET 734 735TEXT runtime·getcallerpc(SB),NOSPLIT,$8-16 736 MOVD FIXED_FRAME+8(R1), R3 // LR saved by caller 737 MOVD runtime·stackBarrierPC(SB), R4 738 CMP R3, R4 739 BNE nobar 740 // Get original return PC. 741 BL runtime·nextBarrierPC(SB) 742 MOVD FIXED_FRAME+0(R1), R3 743nobar: 744 MOVD R3, ret+8(FP) 745 RET 746 747TEXT runtime·setcallerpc(SB),NOSPLIT,$8-16 748 MOVD pc+8(FP), R3 749 MOVD FIXED_FRAME+8(R1), R4 750 MOVD runtime·stackBarrierPC(SB), R5 751 CMP R4, R5 752 BEQ setbar 753 MOVD R3, FIXED_FRAME+8(R1) // set LR in caller 754 RET 755setbar: 756 // Set the stack barrier return PC. 757 MOVD R3, FIXED_FRAME+0(R1) 758 BL runtime·setNextBarrierPC(SB) 759 RET 760 761TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 762 MOVW (R0), R0 763 UNDEF 764 765#define TBRL 268 766#define TBRU 269 /* Time base Upper/Lower */ 767 768// int64 runtime·cputicks(void) 769TEXT runtime·cputicks(SB),NOSPLIT,$0-8 770 MOVW SPR(TBRU), R4 771 MOVW SPR(TBRL), R3 772 MOVW SPR(TBRU), R5 773 CMPW R4, R5 774 BNE -4(PC) 775 SLD $32, R5 776 OR R5, R3 777 MOVD R3, ret+0(FP) 778 RET 779 780// memhash_varlen(p unsafe.Pointer, h seed) uintptr 781// redirects to memhash(p, h, size) using the size 782// stored in the closure. 783TEXT runtime·memhash_varlen(SB),NOSPLIT,$40-24 784 GO_ARGS 785 NO_LOCAL_POINTERS 786 MOVD p+0(FP), R3 787 MOVD h+8(FP), R4 788 MOVD 8(R11), R5 789 MOVD R3, FIXED_FRAME+0(R1) 790 MOVD R4, FIXED_FRAME+8(R1) 791 MOVD R5, FIXED_FRAME+16(R1) 792 BL runtime·memhash(SB) 793 MOVD FIXED_FRAME+24(R1), R3 794 MOVD R3, ret+16(FP) 795 RET 796 797// AES hashing not implemented for ppc64 798TEXT runtime·aeshash(SB),NOSPLIT|NOFRAME,$0-0 799 MOVW (R0), R1 800TEXT runtime·aeshash32(SB),NOSPLIT|NOFRAME,$0-0 801 MOVW (R0), R1 802TEXT runtime·aeshash64(SB),NOSPLIT|NOFRAME,$0-0 803 MOVW (R0), R1 804TEXT runtime·aeshashstr(SB),NOSPLIT|NOFRAME,$0-0 805 MOVW (R0), R1 806 807TEXT runtime·memequal(SB),NOSPLIT,$0-25 808 MOVD a+0(FP), R3 809 MOVD b+8(FP), R4 810 MOVD size+16(FP), R5 811 812 BL runtime·memeqbody(SB) 813 MOVB R9, ret+24(FP) 814 RET 815 816// memequal_varlen(a, b unsafe.Pointer) bool 817TEXT runtime·memequal_varlen(SB),NOSPLIT,$40-17 818 MOVD a+0(FP), R3 819 MOVD b+8(FP), R4 820 CMP R3, R4 821 BEQ eq 822 MOVD 8(R11), R5 // compiler stores size at offset 8 in the closure 823 BL runtime·memeqbody(SB) 824 MOVB R9, ret+16(FP) 825 RET 826eq: 827 MOVD $1, R3 828 MOVB R3, ret+16(FP) 829 RET 830 831// Do an efficient memcmp for ppc64le 832// R3 = s1 len 833// R4 = s2 len 834// R5 = s1 addr 835// R6 = s2 addr 836// R7 = addr of return value 837TEXT cmpbodyLE<>(SB),NOSPLIT|NOFRAME,$0-0 838 MOVD R3,R8 // set up length 839 CMP R3,R4,CR2 // unequal? 840 BC 12,8,setuplen // BLT CR2 841 MOVD R4,R8 // use R4 for comparison len 842setuplen: 843 MOVD R8,CTR // set up loop counter 844 CMP R8,$8 // only optimize >=8 845 BLT simplecheck 846 DCBT (R5) // cache hint 847 DCBT (R6) 848 CMP R8,$32 // optimize >= 32 849 MOVD R8,R9 850 BLT setup8a // 8 byte moves only 851setup32a: 852 SRADCC $5,R8,R9 // number of 32 byte chunks 853 MOVD R9,CTR 854 855 // Special processing for 32 bytes or longer. 856 // Loading this way is faster and correct as long as the 857 // doublewords being compared are equal. Once they 858 // are found unequal, reload them in proper byte order 859 // to determine greater or less than. 860loop32a: 861 MOVD 0(R5),R9 // doublewords to compare 862 MOVD 0(R6),R10 // get 4 doublewords 863 MOVD 8(R5),R14 864 MOVD 8(R6),R15 865 CMPU R9,R10 // bytes equal? 866 MOVD $0,R16 // set up for cmpne 867 BNE cmpne // further compare for LT or GT 868 MOVD 16(R5),R9 // get next pair of doublewords 869 MOVD 16(R6),R10 870 CMPU R14,R15 // bytes match? 871 MOVD $8,R16 // set up for cmpne 872 BNE cmpne // further compare for LT or GT 873 MOVD 24(R5),R14 // get next pair of doublewords 874 MOVD 24(R6),R15 875 CMPU R9,R10 // bytes match? 876 MOVD $16,R16 // set up for cmpne 877 BNE cmpne // further compare for LT or GT 878 MOVD $-8,R16 // for cmpne, R5,R6 already inc by 32 879 ADD $32,R5 // bump up to next 32 880 ADD $32,R6 881 CMPU R14,R15 // bytes match? 882 BC 8,2,loop32a // br ctr and cr 883 BNE cmpne 884 ANDCC $24,R8,R9 // Any 8 byte chunks? 885 BEQ leftover // and result is 0 886setup8a: 887 SRADCC $3,R9,R9 // get the 8 byte count 888 BEQ leftover // shifted value is 0 889 MOVD R9,CTR // loop count for doublewords 890loop8: 891 MOVDBR (R5+R0),R9 // doublewords to compare 892 MOVDBR (R6+R0),R10 // LE compare order 893 ADD $8,R5 894 ADD $8,R6 895 CMPU R9,R10 // match? 896 BC 8,2,loop8 // bt ctr <> 0 && cr 897 BGT greater 898 BLT less 899leftover: 900 ANDCC $7,R8,R9 // check for leftover bytes 901 MOVD R9,CTR // save the ctr 902 BNE simple // leftover bytes 903 BC 12,10,equal // test CR2 for length comparison 904 BC 12,8,less 905 BR greater 906simplecheck: 907 CMP R8,$0 // remaining compare length 0 908 BNE simple // do simple compare 909 BC 12,10,equal // test CR2 for length comparison 910 BC 12,8,less // 1st len < 2nd len, result less 911 BR greater // 1st len > 2nd len must be greater 912simple: 913 MOVBZ 0(R5), R9 // get byte from 1st operand 914 ADD $1,R5 915 MOVBZ 0(R6), R10 // get byte from 2nd operand 916 ADD $1,R6 917 CMPU R9, R10 918 BC 8,2,simple // bc ctr <> 0 && cr 919 BGT greater // 1st > 2nd 920 BLT less // 1st < 2nd 921 BC 12,10,equal // test CR2 for length comparison 922 BC 12,9,greater // 2nd len > 1st len 923 BR less // must be less 924cmpne: // only here is not equal 925 MOVDBR (R5+R16),R8 // reload in reverse order 926 MOVDBR (R6+R16),R9 927 CMPU R8,R9 // compare correct endianness 928 BGT greater // here only if NE 929less: 930 MOVD $-1,R3 931 MOVD R3,(R7) // return value if A < B 932 RET 933equal: 934 MOVD $0,(R7) // return value if A == B 935 RET 936greater: 937 MOVD $1,R3 938 MOVD R3,(R7) // return value if A > B 939 RET 940 941// Do an efficient memcmp for ppc64 (BE) 942// R3 = s1 len 943// R4 = s2 len 944// R5 = s1 addr 945// R6 = s2 addr 946// R7 = addr of return value 947TEXT cmpbodyBE<>(SB),NOSPLIT|NOFRAME,$0-0 948 MOVD R3,R8 // set up length 949 CMP R3,R4,CR2 // unequal? 950 BC 12,8,setuplen // BLT CR2 951 MOVD R4,R8 // use R4 for comparison len 952setuplen: 953 MOVD R8,CTR // set up loop counter 954 CMP R8,$8 // only optimize >=8 955 BLT simplecheck 956 DCBT (R5) // cache hint 957 DCBT (R6) 958 CMP R8,$32 // optimize >= 32 959 MOVD R8,R9 960 BLT setup8a // 8 byte moves only 961 962setup32a: 963 SRADCC $5,R8,R9 // number of 32 byte chunks 964 MOVD R9,CTR 965loop32a: 966 MOVD 0(R5),R9 // doublewords to compare 967 MOVD 0(R6),R10 // get 4 doublewords 968 MOVD 8(R5),R14 969 MOVD 8(R6),R15 970 CMPU R9,R10 // bytes equal? 971 BLT less // found to be less 972 BGT greater // found to be greater 973 MOVD 16(R5),R9 // get next pair of doublewords 974 MOVD 16(R6),R10 975 CMPU R14,R15 // bytes match? 976 BLT less // found less 977 BGT greater // found greater 978 MOVD 24(R5),R14 // get next pair of doublewords 979 MOVD 24(R6),R15 980 CMPU R9,R10 // bytes match? 981 BLT less // found to be less 982 BGT greater // found to be greater 983 ADD $32,R5 // bump up to next 32 984 ADD $32,R6 985 CMPU R14,R15 // bytes match? 986 BC 8,2,loop32a // br ctr and cr 987 BLT less // with BE, byte ordering is 988 BGT greater // good for compare 989 ANDCC $24,R8,R9 // Any 8 byte chunks? 990 BEQ leftover // and result is 0 991setup8a: 992 SRADCC $3,R9,R9 // get the 8 byte count 993 BEQ leftover // shifted value is 0 994 MOVD R9,CTR // loop count for doublewords 995loop8: 996 MOVD (R5),R9 997 MOVD (R6),R10 998 ADD $8,R5 999 ADD $8,R6 1000 CMPU R9,R10 // match? 1001 BC 8,2,loop8 // bt ctr <> 0 && cr 1002 BGT greater 1003 BLT less 1004leftover: 1005 ANDCC $7,R8,R9 // check for leftover bytes 1006 MOVD R9,CTR // save the ctr 1007 BNE simple // leftover bytes 1008 BC 12,10,equal // test CR2 for length comparison 1009 BC 12,8,less 1010 BR greater 1011simplecheck: 1012 CMP R8,$0 // remaining compare length 0 1013 BNE simple // do simple compare 1014 BC 12,10,equal // test CR2 for length comparison 1015 BC 12,8,less // 1st len < 2nd len, result less 1016 BR greater // same len, must be equal 1017simple: 1018 MOVBZ 0(R5),R9 // get byte from 1st operand 1019 ADD $1,R5 1020 MOVBZ 0(R6),R10 // get byte from 2nd operand 1021 ADD $1,R6 1022 CMPU R9,R10 1023 BC 8,2,simple // bc ctr <> 0 && cr 1024 BGT greater // 1st > 2nd 1025 BLT less // 1st < 2nd 1026 BC 12,10,equal // test CR2 for length comparison 1027 BC 12,9,greater // 2nd len > 1st len 1028less: 1029 MOVD $-1,R3 1030 MOVD R3,(R7) // return value if A < B 1031 RET 1032equal: 1033 MOVD $0,(R7) // return value if A == B 1034 RET 1035greater: 1036 MOVD $1,R3 1037 MOVD R3,(R7) // return value if A > B 1038 RET 1039 1040// Do an efficient memequal for ppc64 1041// R3 = s1 1042// R4 = s2 1043// R5 = len 1044// R9 = return value 1045TEXT runtime·memeqbody(SB),NOSPLIT|NOFRAME,$0-0 1046 MOVD R5,CTR 1047 CMP R5,$8 // only optimize >=8 1048 BLT simplecheck 1049 DCBT (R3) // cache hint 1050 DCBT (R4) 1051 CMP R5,$32 // optimize >= 32 1052 MOVD R5,R6 // needed if setup8a branch 1053 BLT setup8a // 8 byte moves only 1054setup32a: // 8 byte aligned, >= 32 bytes 1055 SRADCC $5,R5,R6 // number of 32 byte chunks to compare 1056 MOVD R6,CTR 1057loop32a: 1058 MOVD 0(R3),R6 // doublewords to compare 1059 MOVD 0(R4),R7 1060 MOVD 8(R3),R8 // 1061 MOVD 8(R4),R9 1062 CMP R6,R7 // bytes batch? 1063 BNE noteq 1064 MOVD 16(R3),R6 1065 MOVD 16(R4),R7 1066 CMP R8,R9 // bytes match? 1067 MOVD 24(R3),R8 1068 MOVD 24(R4),R9 1069 BNE noteq 1070 CMP R6,R7 // bytes match? 1071 BNE noteq 1072 ADD $32,R3 // bump up to next 32 1073 ADD $32,R4 1074 CMP R8,R9 // bytes match? 1075 BC 8,2,loop32a // br ctr and cr 1076 BNE noteq 1077 ANDCC $24,R5,R6 // Any 8 byte chunks? 1078 BEQ leftover // and result is 0 1079setup8a: 1080 SRADCC $3,R6,R6 // get the 8 byte count 1081 BEQ leftover // shifted value is 0 1082 MOVD R6,CTR 1083loop8: 1084 MOVD 0(R3),R6 // doublewords to compare 1085 ADD $8,R3 1086 MOVD 0(R4),R7 1087 ADD $8,R4 1088 CMP R6,R7 // match? 1089 BC 8,2,loop8 // bt ctr <> 0 && cr 1090 BNE noteq 1091leftover: 1092 ANDCC $7,R5,R6 // check for leftover bytes 1093 BEQ equal 1094 MOVD R6,CTR 1095 BR simple 1096simplecheck: 1097 CMP R5,$0 1098 BEQ equal 1099simple: 1100 MOVBZ 0(R3), R6 1101 ADD $1,R3 1102 MOVBZ 0(R4), R7 1103 ADD $1,R4 1104 CMP R6, R7 1105 BNE noteq 1106 BC 8,2,simple 1107 BNE noteq 1108 BR equal 1109noteq: 1110 MOVD $0, R9 1111 RET 1112equal: 1113 MOVD $1, R9 1114 RET 1115 1116// eqstring tests whether two strings are equal. 1117// The compiler guarantees that strings passed 1118// to eqstring have equal length. 1119// See runtime_test.go:eqstring_generic for 1120// equivalent Go code. 1121TEXT runtime·eqstring(SB),NOSPLIT,$0-33 1122 MOVD s1_base+0(FP), R3 1123 MOVD s2_base+16(FP), R4 1124 MOVD $1, R5 1125 MOVB R5, ret+32(FP) 1126 CMP R3, R4 1127 BNE 2(PC) 1128 RET 1129 MOVD s1_len+8(FP), R5 1130 BL runtime·memeqbody(SB) 1131 MOVB R9, ret+32(FP) 1132 RET 1133 1134TEXT bytes·Equal(SB),NOSPLIT,$0-49 1135 MOVD a_len+8(FP), R4 1136 MOVD b_len+32(FP), R5 1137 CMP R5, R4 // unequal lengths are not equal 1138 BNE noteq 1139 MOVD a+0(FP), R3 1140 MOVD b+24(FP), R4 1141 BL runtime·memeqbody(SB) 1142 1143 MOVBZ R9,ret+48(FP) 1144 RET 1145 1146noteq: 1147 MOVBZ $0,ret+48(FP) 1148 RET 1149 1150equal: 1151 MOVD $1,R3 1152 MOVBZ R3,ret+48(FP) 1153 RET 1154 1155TEXT bytes·IndexByte(SB),NOSPLIT,$0-40 1156 MOVD s+0(FP), R3 1157 MOVD s_len+8(FP), R4 1158 MOVBZ c+24(FP), R5 // byte to find 1159 MOVD R3, R6 // store base for later 1160 SUB $1, R3 1161 ADD R3, R4 // end-1 1162 1163loop: 1164 CMP R3, R4 1165 BEQ notfound 1166 MOVBZU 1(R3), R7 1167 CMP R7, R5 1168 BNE loop 1169 1170 SUB R6, R3 // remove base 1171 MOVD R3, ret+32(FP) 1172 RET 1173 1174notfound: 1175 MOVD $-1, R3 1176 MOVD R3, ret+32(FP) 1177 RET 1178 1179TEXT strings·IndexByte(SB),NOSPLIT,$0-32 1180 MOVD p+0(FP), R3 1181 MOVD b_len+8(FP), R4 1182 MOVBZ c+16(FP), R5 // byte to find 1183 MOVD R3, R6 // store base for later 1184 SUB $1, R3 1185 ADD R3, R4 // end-1 1186 1187loop: 1188 CMP R3, R4 1189 BEQ notfound 1190 MOVBZU 1(R3), R7 1191 CMP R7, R5 1192 BNE loop 1193 1194 SUB R6, R3 // remove base 1195 MOVD R3, ret+24(FP) 1196 RET 1197 1198notfound: 1199 MOVD $-1, R3 1200 MOVD R3, ret+24(FP) 1201 RET 1202 1203TEXT runtime·cmpstring(SB),NOSPLIT|NOFRAME,$0-40 1204 MOVD s1_base+0(FP), R5 1205 MOVD s1_len+8(FP), R3 1206 MOVD s2_base+16(FP), R6 1207 MOVD s2_len+24(FP), R4 1208 MOVD $ret+32(FP), R7 1209#ifdef GOARCH_ppc64le 1210 BR cmpbodyLE<>(SB) 1211#else 1212 BR cmpbodyBE<>(SB) 1213#endif 1214 1215TEXT bytes·Compare(SB),NOSPLIT|NOFRAME,$0-56 1216 MOVD s1+0(FP), R5 1217 MOVD s1+8(FP), R3 1218 MOVD s2+24(FP), R6 1219 MOVD s2+32(FP), R4 1220 MOVD $ret+48(FP), R7 1221#ifdef GOARCH_ppc64le 1222 BR cmpbodyLE<>(SB) 1223#else 1224 BR cmpbodyBE<>(SB) 1225#endif 1226 1227TEXT runtime·fastrand(SB), NOSPLIT, $0-4 1228 MOVD g_m(g), R4 1229 MOVWZ m_fastrand(R4), R3 1230 ADD R3, R3 1231 CMPW R3, $0 1232 BGE 2(PC) 1233 XOR $0x88888eef, R3 1234 MOVW R3, m_fastrand(R4) 1235 MOVW R3, ret+0(FP) 1236 RET 1237 1238TEXT runtime·return0(SB), NOSPLIT, $0 1239 MOVW $0, R3 1240 RET 1241 1242// Called from cgo wrappers, this function returns g->m->curg.stack.hi. 1243// Must obey the gcc calling convention. 1244TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 1245 // g (R30) and R31 are callee-save in the C ABI, so save them 1246 MOVD g, R4 1247 MOVD R31, R5 1248 MOVD LR, R6 1249 1250 BL runtime·load_g(SB) // clobbers g (R30), R31 1251 MOVD g_m(g), R3 1252 MOVD m_curg(R3), R3 1253 MOVD (g_stack+stack_hi)(R3), R3 1254 1255 MOVD R4, g 1256 MOVD R5, R31 1257 MOVD R6, LR 1258 RET 1259 1260// The top-most function running on a goroutine 1261// returns to goexit+PCQuantum. 1262// 1263// When dynamically linking Go, it can be returned to from a function 1264// implemented in a different module and so needs to reload the TOC pointer 1265// from the stack (although this function declares that it does not set up x-a 1266// frame, newproc1 does in fact allocate one for goexit and saves the TOC 1267// pointer in the correct place). 1268// goexit+_PCQuantum is halfway through the usual global entry point prologue 1269// that derives r2 from r12 which is a bit silly, but not harmful. 1270TEXT runtime·goexit(SB),NOSPLIT|NOFRAME,$0-0 1271 MOVD 24(R1), R2 1272 BL runtime·goexit1(SB) // does not return 1273 // traceback from goexit1 must hit code range of goexit 1274 MOVD R0, R0 // NOP 1275 1276TEXT runtime·prefetcht0(SB),NOSPLIT,$0-8 1277 RET 1278 1279TEXT runtime·prefetcht1(SB),NOSPLIT,$0-8 1280 RET 1281 1282TEXT runtime·prefetcht2(SB),NOSPLIT,$0-8 1283 RET 1284 1285TEXT runtime·prefetchnta(SB),NOSPLIT,$0-8 1286 RET 1287 1288TEXT runtime·sigreturn(SB),NOSPLIT,$0-0 1289 RET 1290 1291// prepGoExitFrame saves the current TOC pointer (i.e. the TOC pointer for the 1292// module containing runtime) to the frame that goexit will execute in when 1293// the goroutine exits. It's implemented in assembly mainly because that's the 1294// easiest way to get access to R2. 1295TEXT runtime·prepGoExitFrame(SB),NOSPLIT,$0-8 1296 MOVD sp+0(FP), R3 1297 MOVD R2, 24(R3) 1298 RET 1299 1300TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 1301 ADD $-8, R1 1302 MOVD R31, 0(R1) 1303 MOVD runtime·lastmoduledatap(SB), R4 1304 MOVD R3, moduledata_next(R4) 1305 MOVD R3, runtime·lastmoduledatap(SB) 1306 MOVD 0(R1), R31 1307 ADD $8, R1 1308 RET 1309 1310TEXT ·checkASM(SB),NOSPLIT,$0-1 1311 MOVW $1, R3 1312 MOVB R3, ret+0(FP) 1313 RET 1314