github.com/geraldss/go/src@v0.0.0-20210511222824-ac7d0ebfc235/runtime/asm_s390x.s (about) 1 // Copyright 2016 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 #include "go_asm.h" 6 #include "go_tls.h" 7 #include "funcdata.h" 8 #include "textflag.h" 9 10 // _rt0_s390x_lib is common startup code for s390x systems when 11 // using -buildmode=c-archive or -buildmode=c-shared. The linker will 12 // arrange to invoke this function as a global constructor (for 13 // c-archive) or when the shared library is loaded (for c-shared). 14 // We expect argc and argv to be passed in the usual C ABI registers 15 // R2 and R3. 16 TEXT _rt0_s390x_lib(SB), NOSPLIT|NOFRAME, $0 17 STMG R6, R15, 48(R15) 18 MOVD R2, _rt0_s390x_lib_argc<>(SB) 19 MOVD R3, _rt0_s390x_lib_argv<>(SB) 20 21 // Save R6-R15 in the register save area of the calling function. 22 STMG R6, R15, 48(R15) 23 24 // Allocate 80 bytes on the stack. 25 MOVD $-80(R15), R15 26 27 // Save F8-F15 in our stack frame. 28 FMOVD F8, 16(R15) 29 FMOVD F9, 24(R15) 30 FMOVD F10, 32(R15) 31 FMOVD F11, 40(R15) 32 FMOVD F12, 48(R15) 33 FMOVD F13, 56(R15) 34 FMOVD F14, 64(R15) 35 FMOVD F15, 72(R15) 36 37 // Synchronous initialization. 38 MOVD $runtime·libpreinit(SB), R1 39 BL R1 40 41 // Create a new thread to finish Go runtime initialization. 42 MOVD _cgo_sys_thread_create(SB), R1 43 CMP R1, $0 44 BEQ nocgo 45 MOVD $_rt0_s390x_lib_go(SB), R2 46 MOVD $0, R3 47 BL R1 48 BR restore 49 50 nocgo: 51 MOVD $0x800000, R1 // stacksize 52 MOVD R1, 0(R15) 53 MOVD $_rt0_s390x_lib_go(SB), R1 54 MOVD R1, 8(R15) // fn 55 MOVD $runtime·newosproc(SB), R1 56 BL R1 57 58 restore: 59 // Restore F8-F15 from our stack frame. 60 FMOVD 16(R15), F8 61 FMOVD 24(R15), F9 62 FMOVD 32(R15), F10 63 FMOVD 40(R15), F11 64 FMOVD 48(R15), F12 65 FMOVD 56(R15), F13 66 FMOVD 64(R15), F14 67 FMOVD 72(R15), F15 68 MOVD $80(R15), R15 69 70 // Restore R6-R15. 71 LMG 48(R15), R6, R15 72 RET 73 74 // _rt0_s390x_lib_go initializes the Go runtime. 75 // This is started in a separate thread by _rt0_s390x_lib. 76 TEXT _rt0_s390x_lib_go(SB), NOSPLIT|NOFRAME, $0 77 MOVD _rt0_s390x_lib_argc<>(SB), R2 78 MOVD _rt0_s390x_lib_argv<>(SB), R3 79 MOVD $runtime·rt0_go(SB), R1 80 BR R1 81 82 DATA _rt0_s390x_lib_argc<>(SB)/8, $0 83 GLOBL _rt0_s390x_lib_argc<>(SB), NOPTR, $8 84 DATA _rt0_s90x_lib_argv<>(SB)/8, $0 85 GLOBL _rt0_s390x_lib_argv<>(SB), NOPTR, $8 86 87 TEXT runtime·rt0_go(SB),NOSPLIT,$0 88 // R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer 89 // C TLS base pointer in AR0:AR1 90 91 // initialize essential registers 92 XOR R0, R0 93 94 SUB $24, R15 95 MOVW R2, 8(R15) // argc 96 MOVD R3, 16(R15) // argv 97 98 // create istack out of the given (operating system) stack. 99 // _cgo_init may update stackguard. 100 MOVD $runtime·g0(SB), g 101 MOVD R15, R11 102 SUB $(64*1024), R11 103 MOVD R11, g_stackguard0(g) 104 MOVD R11, g_stackguard1(g) 105 MOVD R11, (g_stack+stack_lo)(g) 106 MOVD R15, (g_stack+stack_hi)(g) 107 108 // if there is a _cgo_init, call it using the gcc ABI. 109 MOVD _cgo_init(SB), R11 110 CMPBEQ R11, $0, nocgo 111 MOVW AR0, R4 // (AR0 << 32 | AR1) is the TLS base pointer; MOVD is translated to EAR 112 SLD $32, R4, R4 113 MOVW AR1, R4 // arg 2: TLS base pointer 114 MOVD $setg_gcc<>(SB), R3 // arg 1: setg 115 MOVD g, R2 // arg 0: G 116 // C functions expect 160 bytes of space on caller stack frame 117 // and an 8-byte aligned stack pointer 118 MOVD R15, R9 // save current stack (R9 is preserved in the Linux ABI) 119 SUB $160, R15 // reserve 160 bytes 120 MOVD $~7, R6 121 AND R6, R15 // 8-byte align 122 BL R11 // this call clobbers volatile registers according to Linux ABI (R0-R5, R14) 123 MOVD R9, R15 // restore stack 124 XOR R0, R0 // zero R0 125 126 nocgo: 127 // update stackguard after _cgo_init 128 MOVD (g_stack+stack_lo)(g), R2 129 ADD $const__StackGuard, R2 130 MOVD R2, g_stackguard0(g) 131 MOVD R2, g_stackguard1(g) 132 133 // set the per-goroutine and per-mach "registers" 134 MOVD $runtime·m0(SB), R2 135 136 // save m->g0 = g0 137 MOVD g, m_g0(R2) 138 // save m0 to g0->m 139 MOVD R2, g_m(g) 140 141 BL runtime·check(SB) 142 143 // argc/argv are already prepared on stack 144 BL runtime·args(SB) 145 BL runtime·osinit(SB) 146 BL runtime·schedinit(SB) 147 148 // create a new goroutine to start program 149 MOVD $runtime·mainPC(SB), R2 // entry 150 SUB $24, R15 151 MOVD R2, 16(R15) 152 MOVD $0, 8(R15) 153 MOVD $0, 0(R15) 154 BL runtime·newproc(SB) 155 ADD $24, R15 156 157 // start this M 158 BL runtime·mstart(SB) 159 160 MOVD $0, 1(R0) 161 RET 162 163 DATA runtime·mainPC+0(SB)/8,$runtime·main(SB) 164 GLOBL runtime·mainPC(SB),RODATA,$8 165 166 TEXT runtime·breakpoint(SB),NOSPLIT|NOFRAME,$0-0 167 MOVD $0, 2(R0) 168 RET 169 170 TEXT runtime·asminit(SB),NOSPLIT|NOFRAME,$0-0 171 RET 172 173 /* 174 * go-routine 175 */ 176 177 // void gosave(Gobuf*) 178 // save state in Gobuf; setjmp 179 TEXT runtime·gosave(SB), NOSPLIT, $-8-8 180 MOVD buf+0(FP), R3 181 MOVD R15, gobuf_sp(R3) 182 MOVD LR, gobuf_pc(R3) 183 MOVD g, gobuf_g(R3) 184 MOVD $0, gobuf_lr(R3) 185 MOVD $0, gobuf_ret(R3) 186 // Assert ctxt is zero. See func save. 187 MOVD gobuf_ctxt(R3), R3 188 CMPBEQ R3, $0, 2(PC) 189 BL runtime·badctxt(SB) 190 RET 191 192 // void gogo(Gobuf*) 193 // restore state from Gobuf; longjmp 194 TEXT runtime·gogo(SB), NOSPLIT, $16-8 195 MOVD buf+0(FP), R5 196 MOVD gobuf_g(R5), g // make sure g is not nil 197 BL runtime·save_g(SB) 198 199 MOVD 0(g), R4 200 MOVD gobuf_sp(R5), R15 201 MOVD gobuf_lr(R5), LR 202 MOVD gobuf_ret(R5), R3 203 MOVD gobuf_ctxt(R5), R12 204 MOVD $0, gobuf_sp(R5) 205 MOVD $0, gobuf_ret(R5) 206 MOVD $0, gobuf_lr(R5) 207 MOVD $0, gobuf_ctxt(R5) 208 CMP R0, R0 // set condition codes for == test, needed by stack split 209 MOVD gobuf_pc(R5), R6 210 BR (R6) 211 212 // void mcall(fn func(*g)) 213 // Switch to m->g0's stack, call fn(g). 214 // Fn must never return. It should gogo(&g->sched) 215 // to keep running g. 216 TEXT runtime·mcall(SB), NOSPLIT, $-8-8 217 // Save caller state in g->sched 218 MOVD R15, (g_sched+gobuf_sp)(g) 219 MOVD LR, (g_sched+gobuf_pc)(g) 220 MOVD $0, (g_sched+gobuf_lr)(g) 221 MOVD g, (g_sched+gobuf_g)(g) 222 223 // Switch to m->g0 & its stack, call fn. 224 MOVD g, R3 225 MOVD g_m(g), R8 226 MOVD m_g0(R8), g 227 BL runtime·save_g(SB) 228 CMP g, R3 229 BNE 2(PC) 230 BR runtime·badmcall(SB) 231 MOVD fn+0(FP), R12 // context 232 MOVD 0(R12), R4 // code pointer 233 MOVD (g_sched+gobuf_sp)(g), R15 // sp = m->g0->sched.sp 234 SUB $16, R15 235 MOVD R3, 8(R15) 236 MOVD $0, 0(R15) 237 BL (R4) 238 BR runtime·badmcall2(SB) 239 240 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 241 // of the G stack. We need to distinguish the routine that 242 // lives at the bottom of the G stack from the one that lives 243 // at the top of the system stack because the one at the top of 244 // the system stack terminates the stack walk (see topofstack()). 245 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 246 UNDEF 247 BL (LR) // make sure this function is not leaf 248 RET 249 250 // func systemstack(fn func()) 251 TEXT runtime·systemstack(SB), NOSPLIT, $0-8 252 MOVD fn+0(FP), R3 // R3 = fn 253 MOVD R3, R12 // context 254 MOVD g_m(g), R4 // R4 = m 255 256 MOVD m_gsignal(R4), R5 // R5 = gsignal 257 CMPBEQ g, R5, noswitch 258 259 MOVD m_g0(R4), R5 // R5 = g0 260 CMPBEQ g, R5, noswitch 261 262 MOVD m_curg(R4), R6 263 CMPBEQ g, R6, switch 264 265 // Bad: g is not gsignal, not g0, not curg. What is it? 266 // Hide call from linker nosplit analysis. 267 MOVD $runtime·badsystemstack(SB), R3 268 BL (R3) 269 BL runtime·abort(SB) 270 271 switch: 272 // save our state in g->sched. Pretend to 273 // be systemstack_switch if the G stack is scanned. 274 MOVD $runtime·systemstack_switch(SB), R6 275 ADD $16, R6 // get past prologue 276 MOVD R6, (g_sched+gobuf_pc)(g) 277 MOVD R15, (g_sched+gobuf_sp)(g) 278 MOVD $0, (g_sched+gobuf_lr)(g) 279 MOVD g, (g_sched+gobuf_g)(g) 280 281 // switch to g0 282 MOVD R5, g 283 BL runtime·save_g(SB) 284 MOVD (g_sched+gobuf_sp)(g), R3 285 // make it look like mstart called systemstack on g0, to stop traceback 286 SUB $8, R3 287 MOVD $runtime·mstart(SB), R4 288 MOVD R4, 0(R3) 289 MOVD R3, R15 290 291 // call target function 292 MOVD 0(R12), R3 // code pointer 293 BL (R3) 294 295 // switch back to g 296 MOVD g_m(g), R3 297 MOVD m_curg(R3), g 298 BL runtime·save_g(SB) 299 MOVD (g_sched+gobuf_sp)(g), R15 300 MOVD $0, (g_sched+gobuf_sp)(g) 301 RET 302 303 noswitch: 304 // already on m stack, just call directly 305 // Using a tail call here cleans up tracebacks since we won't stop 306 // at an intermediate systemstack. 307 MOVD 0(R12), R3 // code pointer 308 MOVD 0(R15), LR // restore LR 309 ADD $8, R15 310 BR (R3) 311 312 /* 313 * support for morestack 314 */ 315 316 // Called during function prolog when more stack is needed. 317 // Caller has already loaded: 318 // R3: framesize, R4: argsize, R5: LR 319 // 320 // The traceback routines see morestack on a g0 as being 321 // the top of a stack (for example, morestack calling newstack 322 // calling the scheduler calling newm calling gc), so we must 323 // record an argument size. For that purpose, it has no arguments. 324 TEXT runtime·morestack(SB),NOSPLIT|NOFRAME,$0-0 325 // Cannot grow scheduler stack (m->g0). 326 MOVD g_m(g), R7 327 MOVD m_g0(R7), R8 328 CMPBNE g, R8, 3(PC) 329 BL runtime·badmorestackg0(SB) 330 BL runtime·abort(SB) 331 332 // Cannot grow signal stack (m->gsignal). 333 MOVD m_gsignal(R7), R8 334 CMP g, R8 335 BNE 3(PC) 336 BL runtime·badmorestackgsignal(SB) 337 BL runtime·abort(SB) 338 339 // Called from f. 340 // Set g->sched to context in f. 341 MOVD R15, (g_sched+gobuf_sp)(g) 342 MOVD LR, R8 343 MOVD R8, (g_sched+gobuf_pc)(g) 344 MOVD R5, (g_sched+gobuf_lr)(g) 345 MOVD R12, (g_sched+gobuf_ctxt)(g) 346 347 // Called from f. 348 // Set m->morebuf to f's caller. 349 MOVD R5, (m_morebuf+gobuf_pc)(R7) // f's caller's PC 350 MOVD R15, (m_morebuf+gobuf_sp)(R7) // f's caller's SP 351 MOVD g, (m_morebuf+gobuf_g)(R7) 352 353 // Call newstack on m->g0's stack. 354 MOVD m_g0(R7), g 355 BL runtime·save_g(SB) 356 MOVD (g_sched+gobuf_sp)(g), R15 357 // Create a stack frame on g0 to call newstack. 358 MOVD $0, -8(R15) // Zero saved LR in frame 359 SUB $8, R15 360 BL runtime·newstack(SB) 361 362 // Not reached, but make sure the return PC from the call to newstack 363 // is still in this function, and not the beginning of the next. 364 UNDEF 365 366 TEXT runtime·morestack_noctxt(SB),NOSPLIT|NOFRAME,$0-0 367 MOVD $0, R12 368 BR runtime·morestack(SB) 369 370 // reflectcall: call a function with the given argument list 371 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 372 // we don't have variable-sized frames, so we use a small number 373 // of constant-sized-frame functions to encode a few bits of size in the pc. 374 // Caution: ugly multiline assembly macros in your future! 375 376 #define DISPATCH(NAME,MAXSIZE) \ 377 MOVD $MAXSIZE, R4; \ 378 CMP R3, R4; \ 379 BGT 3(PC); \ 380 MOVD $NAME(SB), R5; \ 381 BR (R5) 382 // Note: can't just "BR NAME(SB)" - bad inlining results. 383 384 TEXT ·reflectcall(SB), NOSPLIT, $-8-32 385 MOVWZ argsize+24(FP), R3 386 DISPATCH(runtime·call16, 16) 387 DISPATCH(runtime·call32, 32) 388 DISPATCH(runtime·call64, 64) 389 DISPATCH(runtime·call128, 128) 390 DISPATCH(runtime·call256, 256) 391 DISPATCH(runtime·call512, 512) 392 DISPATCH(runtime·call1024, 1024) 393 DISPATCH(runtime·call2048, 2048) 394 DISPATCH(runtime·call4096, 4096) 395 DISPATCH(runtime·call8192, 8192) 396 DISPATCH(runtime·call16384, 16384) 397 DISPATCH(runtime·call32768, 32768) 398 DISPATCH(runtime·call65536, 65536) 399 DISPATCH(runtime·call131072, 131072) 400 DISPATCH(runtime·call262144, 262144) 401 DISPATCH(runtime·call524288, 524288) 402 DISPATCH(runtime·call1048576, 1048576) 403 DISPATCH(runtime·call2097152, 2097152) 404 DISPATCH(runtime·call4194304, 4194304) 405 DISPATCH(runtime·call8388608, 8388608) 406 DISPATCH(runtime·call16777216, 16777216) 407 DISPATCH(runtime·call33554432, 33554432) 408 DISPATCH(runtime·call67108864, 67108864) 409 DISPATCH(runtime·call134217728, 134217728) 410 DISPATCH(runtime·call268435456, 268435456) 411 DISPATCH(runtime·call536870912, 536870912) 412 DISPATCH(runtime·call1073741824, 1073741824) 413 MOVD $runtime·badreflectcall(SB), R5 414 BR (R5) 415 416 #define CALLFN(NAME,MAXSIZE) \ 417 TEXT NAME(SB), WRAPPER, $MAXSIZE-24; \ 418 NO_LOCAL_POINTERS; \ 419 /* copy arguments to stack */ \ 420 MOVD arg+16(FP), R4; \ 421 MOVWZ argsize+24(FP), R5; \ 422 MOVD $stack-MAXSIZE(SP), R6; \ 423 loopArgs: /* copy 256 bytes at a time */ \ 424 CMP R5, $256; \ 425 BLT tailArgs; \ 426 SUB $256, R5; \ 427 MVC $256, 0(R4), 0(R6); \ 428 MOVD $256(R4), R4; \ 429 MOVD $256(R6), R6; \ 430 BR loopArgs; \ 431 tailArgs: /* copy remaining bytes */ \ 432 CMP R5, $0; \ 433 BEQ callFunction; \ 434 SUB $1, R5; \ 435 EXRL $callfnMVC<>(SB), R5; \ 436 callFunction: \ 437 MOVD f+8(FP), R12; \ 438 MOVD (R12), R8; \ 439 PCDATA $PCDATA_StackMapIndex, $0; \ 440 BL (R8); \ 441 /* copy return values back */ \ 442 MOVD argtype+0(FP), R7; \ 443 MOVD arg+16(FP), R6; \ 444 MOVWZ n+24(FP), R5; \ 445 MOVD $stack-MAXSIZE(SP), R4; \ 446 MOVWZ retoffset+28(FP), R1; \ 447 ADD R1, R4; \ 448 ADD R1, R6; \ 449 SUB R1, R5; \ 450 BL callRet<>(SB); \ 451 RET 452 453 // callRet copies return values back at the end of call*. This is a 454 // separate function so it can allocate stack space for the arguments 455 // to reflectcallmove. It does not follow the Go ABI; it expects its 456 // arguments in registers. 457 TEXT callRet<>(SB), NOSPLIT, $32-0 458 MOVD R7, 8(R15) 459 MOVD R6, 16(R15) 460 MOVD R4, 24(R15) 461 MOVD R5, 32(R15) 462 BL runtime·reflectcallmove(SB) 463 RET 464 465 CALLFN(·call16, 16) 466 CALLFN(·call32, 32) 467 CALLFN(·call64, 64) 468 CALLFN(·call128, 128) 469 CALLFN(·call256, 256) 470 CALLFN(·call512, 512) 471 CALLFN(·call1024, 1024) 472 CALLFN(·call2048, 2048) 473 CALLFN(·call4096, 4096) 474 CALLFN(·call8192, 8192) 475 CALLFN(·call16384, 16384) 476 CALLFN(·call32768, 32768) 477 CALLFN(·call65536, 65536) 478 CALLFN(·call131072, 131072) 479 CALLFN(·call262144, 262144) 480 CALLFN(·call524288, 524288) 481 CALLFN(·call1048576, 1048576) 482 CALLFN(·call2097152, 2097152) 483 CALLFN(·call4194304, 4194304) 484 CALLFN(·call8388608, 8388608) 485 CALLFN(·call16777216, 16777216) 486 CALLFN(·call33554432, 33554432) 487 CALLFN(·call67108864, 67108864) 488 CALLFN(·call134217728, 134217728) 489 CALLFN(·call268435456, 268435456) 490 CALLFN(·call536870912, 536870912) 491 CALLFN(·call1073741824, 1073741824) 492 493 // Not a function: target for EXRL (execute relative long) instruction. 494 TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0 495 MVC $1, 0(R4), 0(R6) 496 497 TEXT runtime·procyield(SB),NOSPLIT,$0-0 498 RET 499 500 // void jmpdefer(fv, sp); 501 // called from deferreturn. 502 // 1. grab stored LR for caller 503 // 2. sub 6 bytes to get back to BL deferreturn (size of BRASL instruction) 504 // 3. BR to fn 505 TEXT runtime·jmpdefer(SB),NOSPLIT|NOFRAME,$0-16 506 MOVD 0(R15), R1 507 SUB $6, R1, LR 508 509 MOVD fv+0(FP), R12 510 MOVD argp+8(FP), R15 511 SUB $8, R15 512 MOVD 0(R12), R3 513 BR (R3) 514 515 // Save state of caller into g->sched. Smashes R1. 516 TEXT gosave<>(SB),NOSPLIT|NOFRAME,$0 517 MOVD LR, (g_sched+gobuf_pc)(g) 518 MOVD R15, (g_sched+gobuf_sp)(g) 519 MOVD $0, (g_sched+gobuf_lr)(g) 520 MOVD $0, (g_sched+gobuf_ret)(g) 521 // Assert ctxt is zero. See func save. 522 MOVD (g_sched+gobuf_ctxt)(g), R1 523 CMPBEQ R1, $0, 2(PC) 524 BL runtime·badctxt(SB) 525 RET 526 527 // func asmcgocall(fn, arg unsafe.Pointer) int32 528 // Call fn(arg) on the scheduler stack, 529 // aligned appropriately for the gcc ABI. 530 // See cgocall.go for more details. 531 TEXT ·asmcgocall(SB),NOSPLIT,$0-20 532 // R2 = argc; R3 = argv; R11 = temp; R13 = g; R15 = stack pointer 533 // C TLS base pointer in AR0:AR1 534 MOVD fn+0(FP), R3 535 MOVD arg+8(FP), R4 536 537 MOVD R15, R2 // save original stack pointer 538 MOVD g, R5 539 540 // Figure out if we need to switch to m->g0 stack. 541 // We get called to create new OS threads too, and those 542 // come in on the m->g0 stack already. 543 MOVD g_m(g), R6 544 MOVD m_g0(R6), R6 545 CMPBEQ R6, g, g0 546 BL gosave<>(SB) 547 MOVD R6, g 548 BL runtime·save_g(SB) 549 MOVD (g_sched+gobuf_sp)(g), R15 550 551 // Now on a scheduling stack (a pthread-created stack). 552 g0: 553 // Save room for two of our pointers, plus 160 bytes of callee 554 // save area that lives on the caller stack. 555 SUB $176, R15 556 MOVD $~7, R6 557 AND R6, R15 // 8-byte alignment for gcc ABI 558 MOVD R5, 168(R15) // save old g on stack 559 MOVD (g_stack+stack_hi)(R5), R5 560 SUB R2, R5 561 MOVD R5, 160(R15) // save depth in old g stack (can't just save SP, as stack might be copied during a callback) 562 MOVD $0, 0(R15) // clear back chain pointer (TODO can we give it real back trace information?) 563 MOVD R4, R2 // arg in R2 564 BL R3 // can clobber: R0-R5, R14, F0-F3, F5, F7-F15 565 566 XOR R0, R0 // set R0 back to 0. 567 // Restore g, stack pointer. 568 MOVD 168(R15), g 569 BL runtime·save_g(SB) 570 MOVD (g_stack+stack_hi)(g), R5 571 MOVD 160(R15), R6 572 SUB R6, R5 573 MOVD R5, R15 574 575 MOVW R2, ret+16(FP) 576 RET 577 578 // cgocallback(fn, frame unsafe.Pointer, ctxt uintptr) 579 // See cgocall.go for more details. 580 TEXT ·cgocallback(SB),NOSPLIT,$24-24 581 NO_LOCAL_POINTERS 582 583 // Load m and g from thread-local storage. 584 MOVB runtime·iscgo(SB), R3 585 CMPBEQ R3, $0, nocgo 586 BL runtime·load_g(SB) 587 588 nocgo: 589 // If g is nil, Go did not create the current thread. 590 // Call needm to obtain one for temporary use. 591 // In this case, we're running on the thread stack, so there's 592 // lots of space, but the linker doesn't know. Hide the call from 593 // the linker analysis by using an indirect call. 594 CMPBEQ g, $0, needm 595 596 MOVD g_m(g), R8 597 MOVD R8, savedm-8(SP) 598 BR havem 599 600 needm: 601 MOVD g, savedm-8(SP) // g is zero, so is m. 602 MOVD $runtime·needm(SB), R3 603 BL (R3) 604 605 // Set m->sched.sp = SP, so that if a panic happens 606 // during the function we are about to execute, it will 607 // have a valid SP to run on the g0 stack. 608 // The next few lines (after the havem label) 609 // will save this SP onto the stack and then write 610 // the same SP back to m->sched.sp. That seems redundant, 611 // but if an unrecovered panic happens, unwindm will 612 // restore the g->sched.sp from the stack location 613 // and then systemstack will try to use it. If we don't set it here, 614 // that restored SP will be uninitialized (typically 0) and 615 // will not be usable. 616 MOVD g_m(g), R8 617 MOVD m_g0(R8), R3 618 MOVD R15, (g_sched+gobuf_sp)(R3) 619 620 havem: 621 // Now there's a valid m, and we're running on its m->g0. 622 // Save current m->g0->sched.sp on stack and then set it to SP. 623 // Save current sp in m->g0->sched.sp in preparation for 624 // switch back to m->curg stack. 625 // NOTE: unwindm knows that the saved g->sched.sp is at 8(R1) aka savedsp-16(SP). 626 MOVD m_g0(R8), R3 627 MOVD (g_sched+gobuf_sp)(R3), R4 628 MOVD R4, savedsp-24(SP) // must match frame size 629 MOVD R15, (g_sched+gobuf_sp)(R3) 630 631 // Switch to m->curg stack and call runtime.cgocallbackg. 632 // Because we are taking over the execution of m->curg 633 // but *not* resuming what had been running, we need to 634 // save that information (m->curg->sched) so we can restore it. 635 // We can restore m->curg->sched.sp easily, because calling 636 // runtime.cgocallbackg leaves SP unchanged upon return. 637 // To save m->curg->sched.pc, we push it onto the curg stack and 638 // open a frame the same size as cgocallback's g0 frame. 639 // Once we switch to the curg stack, the pushed PC will appear 640 // to be the return PC of cgocallback, so that the traceback 641 // will seamlessly trace back into the earlier calls. 642 MOVD m_curg(R8), g 643 BL runtime·save_g(SB) 644 MOVD (g_sched+gobuf_sp)(g), R4 // prepare stack as R4 645 MOVD (g_sched+gobuf_pc)(g), R5 646 MOVD R5, -(24+8)(R4) // "saved LR"; must match frame size 647 // Gather our arguments into registers. 648 MOVD fn+0(FP), R1 649 MOVD frame+8(FP), R2 650 MOVD ctxt+16(FP), R3 651 MOVD $-(24+8)(R4), R15 // switch stack; must match frame size 652 MOVD R1, 8(R15) 653 MOVD R2, 16(R15) 654 MOVD R3, 24(R15) 655 BL runtime·cgocallbackg(SB) 656 657 // Restore g->sched (== m->curg->sched) from saved values. 658 MOVD 0(R15), R5 659 MOVD R5, (g_sched+gobuf_pc)(g) 660 MOVD $(24+8)(R15), R4 // must match frame size 661 MOVD R4, (g_sched+gobuf_sp)(g) 662 663 // Switch back to m->g0's stack and restore m->g0->sched.sp. 664 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 665 // so we do not have to restore it.) 666 MOVD g_m(g), R8 667 MOVD m_g0(R8), g 668 BL runtime·save_g(SB) 669 MOVD (g_sched+gobuf_sp)(g), R15 670 MOVD savedsp-24(SP), R4 // must match frame size 671 MOVD R4, (g_sched+gobuf_sp)(g) 672 673 // If the m on entry was nil, we called needm above to borrow an m 674 // for the duration of the call. Since the call is over, return it with dropm. 675 MOVD savedm-8(SP), R6 676 CMPBNE R6, $0, droppedm 677 MOVD $runtime·dropm(SB), R3 678 BL (R3) 679 droppedm: 680 681 // Done! 682 RET 683 684 // void setg(G*); set g. for use by needm. 685 TEXT runtime·setg(SB), NOSPLIT, $0-8 686 MOVD gg+0(FP), g 687 // This only happens if iscgo, so jump straight to save_g 688 BL runtime·save_g(SB) 689 RET 690 691 // void setg_gcc(G*); set g in C TLS. 692 // Must obey the gcc calling convention. 693 TEXT setg_gcc<>(SB),NOSPLIT|NOFRAME,$0-0 694 // The standard prologue clobbers LR (R14), which is callee-save in 695 // the C ABI, so we have to use NOFRAME and save LR ourselves. 696 MOVD LR, R1 697 // Also save g, R10, and R11 since they're callee-save in C ABI 698 MOVD R10, R3 699 MOVD g, R4 700 MOVD R11, R5 701 702 MOVD R2, g 703 BL runtime·save_g(SB) 704 705 MOVD R5, R11 706 MOVD R4, g 707 MOVD R3, R10 708 MOVD R1, LR 709 RET 710 711 TEXT runtime·abort(SB),NOSPLIT|NOFRAME,$0-0 712 MOVW (R0), R0 713 UNDEF 714 715 // int64 runtime·cputicks(void) 716 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 717 // The TOD clock on s390 counts from the year 1900 in ~250ps intervals. 718 // This means that since about 1972 the msb has been set, making the 719 // result of a call to STORE CLOCK (stck) a negative number. 720 // We clear the msb to make it positive. 721 STCK ret+0(FP) // serialises before and after call 722 MOVD ret+0(FP), R3 // R3 will wrap to 0 in the year 2043 723 SLD $1, R3 724 SRD $1, R3 725 MOVD R3, ret+0(FP) 726 RET 727 728 // AES hashing not implemented for s390x 729 TEXT runtime·memhash(SB),NOSPLIT|NOFRAME,$0-32 730 JMP runtime·memhashFallback(SB) 731 TEXT runtime·strhash(SB),NOSPLIT|NOFRAME,$0-24 732 JMP runtime·strhashFallback(SB) 733 TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-24 734 JMP runtime·memhash32Fallback(SB) 735 TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-24 736 JMP runtime·memhash64Fallback(SB) 737 738 TEXT runtime·return0(SB), NOSPLIT, $0 739 MOVW $0, R3 740 RET 741 742 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 743 // Must obey the gcc calling convention. 744 TEXT _cgo_topofstack(SB),NOSPLIT|NOFRAME,$0 745 // g (R13), R10, R11 and LR (R14) are callee-save in the C ABI, so save them 746 MOVD g, R1 747 MOVD R10, R3 748 MOVD LR, R4 749 MOVD R11, R5 750 751 BL runtime·load_g(SB) // clobbers g (R13), R10, R11 752 MOVD g_m(g), R2 753 MOVD m_curg(R2), R2 754 MOVD (g_stack+stack_hi)(R2), R2 755 756 MOVD R1, g 757 MOVD R3, R10 758 MOVD R4, LR 759 MOVD R5, R11 760 RET 761 762 // The top-most function running on a goroutine 763 // returns to goexit+PCQuantum. 764 TEXT runtime·goexit(SB),NOSPLIT|NOFRAME|TOPFRAME,$0-0 765 BYTE $0x07; BYTE $0x00; // 2-byte nop 766 BL runtime·goexit1(SB) // does not return 767 // traceback from goexit1 must hit code range of goexit 768 BYTE $0x07; BYTE $0x00; // 2-byte nop 769 770 TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0 771 // Stores are already ordered on s390x, so this is just a 772 // compile barrier. 773 RET 774 775 // This is called from .init_array and follows the platform, not Go, ABI. 776 // We are overly conservative. We could only save the registers we use. 777 // However, since this function is only called once per loaded module 778 // performance is unimportant. 779 TEXT runtime·addmoduledata(SB),NOSPLIT|NOFRAME,$0-0 780 // Save R6-R15 in the register save area of the calling function. 781 // Don't bother saving F8-F15 as we aren't doing any calls. 782 STMG R6, R15, 48(R15) 783 784 // append the argument (passed in R2, as per the ELF ABI) to the 785 // moduledata linked list. 786 MOVD runtime·lastmoduledatap(SB), R1 787 MOVD R2, moduledata_next(R1) 788 MOVD R2, runtime·lastmoduledatap(SB) 789 790 // Restore R6-R15. 791 LMG 48(R15), R6, R15 792 RET 793 794 TEXT ·checkASM(SB),NOSPLIT,$0-1 795 MOVB $1, ret+0(FP) 796 RET 797 798 // gcWriteBarrier performs a heap pointer write and informs the GC. 799 // 800 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 801 // - R2 is the destination of the write 802 // - R3 is the value being written at R2. 803 // It clobbers R10 (the temp register). 804 // It does not clobber any other general-purpose registers, 805 // but may clobber others (e.g., floating point registers). 806 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$104 807 // Save the registers clobbered by the fast path. 808 MOVD R1, 96(R15) 809 MOVD R4, 104(R15) 810 MOVD g_m(g), R1 811 MOVD m_p(R1), R1 812 // Increment wbBuf.next position. 813 MOVD $16, R4 814 ADD (p_wbBuf+wbBuf_next)(R1), R4 815 MOVD R4, (p_wbBuf+wbBuf_next)(R1) 816 MOVD (p_wbBuf+wbBuf_end)(R1), R1 817 // Record the write. 818 MOVD R3, -16(R4) // Record value 819 MOVD (R2), R10 // TODO: This turns bad writes into bad reads. 820 MOVD R10, -8(R4) // Record *slot 821 // Is the buffer full? 822 CMPBEQ R4, R1, flush 823 ret: 824 MOVD 96(R15), R1 825 MOVD 104(R15), R4 826 // Do the write. 827 MOVD R3, (R2) 828 RET 829 830 flush: 831 // Save all general purpose registers since these could be 832 // clobbered by wbBufFlush and were not saved by the caller. 833 STMG R2, R3, 8(R15) // set R2 and R3 as arguments for wbBufFlush 834 MOVD R0, 24(R15) 835 // R1 already saved. 836 // R4 already saved. 837 STMG R5, R12, 32(R15) // save R5 - R12 838 // R13 is g. 839 // R14 is LR. 840 // R15 is SP. 841 842 // This takes arguments R2 and R3. 843 CALL runtime·wbBufFlush(SB) 844 845 LMG 8(R15), R2, R3 // restore R2 - R3 846 MOVD 24(R15), R0 // restore R0 847 LMG 32(R15), R5, R12 // restore R5 - R12 848 JMP ret 849 850 // Note: these functions use a special calling convention to save generated code space. 851 // Arguments are passed in registers, but the space for those arguments are allocated 852 // in the caller's stack frame. These stubs write the args into that stack space and 853 // then tail call to the corresponding runtime handler. 854 // The tail call makes these stubs disappear in backtraces. 855 TEXT runtime·panicIndex(SB),NOSPLIT,$0-16 856 MOVD R0, x+0(FP) 857 MOVD R1, y+8(FP) 858 JMP runtime·goPanicIndex(SB) 859 TEXT runtime·panicIndexU(SB),NOSPLIT,$0-16 860 MOVD R0, x+0(FP) 861 MOVD R1, y+8(FP) 862 JMP runtime·goPanicIndexU(SB) 863 TEXT runtime·panicSliceAlen(SB),NOSPLIT,$0-16 864 MOVD R1, x+0(FP) 865 MOVD R2, y+8(FP) 866 JMP runtime·goPanicSliceAlen(SB) 867 TEXT runtime·panicSliceAlenU(SB),NOSPLIT,$0-16 868 MOVD R1, x+0(FP) 869 MOVD R2, y+8(FP) 870 JMP runtime·goPanicSliceAlenU(SB) 871 TEXT runtime·panicSliceAcap(SB),NOSPLIT,$0-16 872 MOVD R1, x+0(FP) 873 MOVD R2, y+8(FP) 874 JMP runtime·goPanicSliceAcap(SB) 875 TEXT runtime·panicSliceAcapU(SB),NOSPLIT,$0-16 876 MOVD R1, x+0(FP) 877 MOVD R2, y+8(FP) 878 JMP runtime·goPanicSliceAcapU(SB) 879 TEXT runtime·panicSliceB(SB),NOSPLIT,$0-16 880 MOVD R0, x+0(FP) 881 MOVD R1, y+8(FP) 882 JMP runtime·goPanicSliceB(SB) 883 TEXT runtime·panicSliceBU(SB),NOSPLIT,$0-16 884 MOVD R0, x+0(FP) 885 MOVD R1, y+8(FP) 886 JMP runtime·goPanicSliceBU(SB) 887 TEXT runtime·panicSlice3Alen(SB),NOSPLIT,$0-16 888 MOVD R2, x+0(FP) 889 MOVD R3, y+8(FP) 890 JMP runtime·goPanicSlice3Alen(SB) 891 TEXT runtime·panicSlice3AlenU(SB),NOSPLIT,$0-16 892 MOVD R2, x+0(FP) 893 MOVD R3, y+8(FP) 894 JMP runtime·goPanicSlice3AlenU(SB) 895 TEXT runtime·panicSlice3Acap(SB),NOSPLIT,$0-16 896 MOVD R2, x+0(FP) 897 MOVD R3, y+8(FP) 898 JMP runtime·goPanicSlice3Acap(SB) 899 TEXT runtime·panicSlice3AcapU(SB),NOSPLIT,$0-16 900 MOVD R2, x+0(FP) 901 MOVD R3, y+8(FP) 902 JMP runtime·goPanicSlice3AcapU(SB) 903 TEXT runtime·panicSlice3B(SB),NOSPLIT,$0-16 904 MOVD R1, x+0(FP) 905 MOVD R2, y+8(FP) 906 JMP runtime·goPanicSlice3B(SB) 907 TEXT runtime·panicSlice3BU(SB),NOSPLIT,$0-16 908 MOVD R1, x+0(FP) 909 MOVD R2, y+8(FP) 910 JMP runtime·goPanicSlice3BU(SB) 911 TEXT runtime·panicSlice3C(SB),NOSPLIT,$0-16 912 MOVD R0, x+0(FP) 913 MOVD R1, y+8(FP) 914 JMP runtime·goPanicSlice3C(SB) 915 TEXT runtime·panicSlice3CU(SB),NOSPLIT,$0-16 916 MOVD R0, x+0(FP) 917 MOVD R1, y+8(FP) 918 JMP runtime·goPanicSlice3CU(SB)