github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/asm_amd64p32.s (about) 1 // Copyright 2009 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 TEXT runtime·rt0_go(SB),NOSPLIT,$0 11 // copy arguments forward on an even stack 12 MOVL argc+0(FP), AX 13 MOVL argv+4(FP), BX 14 MOVL SP, CX 15 SUBL $128, CX // plenty of scratch 16 ANDL $~15, CX 17 MOVL CX, SP 18 19 MOVL AX, 16(SP) 20 MOVL BX, 24(SP) 21 22 // create istack out of the given (operating system) stack. 23 MOVL $runtime·g0(SB), DI 24 LEAL (-64*1024+104)(SP), BX 25 MOVL BX, g_stackguard0(DI) 26 MOVL BX, g_stackguard1(DI) 27 MOVL BX, (g_stack+stack_lo)(DI) 28 MOVL SP, (g_stack+stack_hi)(DI) 29 30 // find out information about the processor we're on 31 MOVL $0, AX 32 CPUID 33 CMPL AX, $0 34 JE nocpuinfo 35 36 CMPL BX, $0x756E6547 // "Genu" 37 JNE notintel 38 CMPL DX, $0x49656E69 // "ineI" 39 JNE notintel 40 CMPL CX, $0x6C65746E // "ntel" 41 JNE notintel 42 MOVB $1, runtime·isIntel(SB) 43 notintel: 44 45 // Load EAX=1 cpuid flags 46 MOVL $1, AX 47 CPUID 48 MOVL AX, runtime·processorVersionInfo(SB) 49 50 nocpuinfo: 51 LEAL runtime·m0+m_tls(SB), DI 52 CALL runtime·settls(SB) 53 54 // store through it, to make sure it works 55 get_tls(BX) 56 MOVQ $0x123, g(BX) 57 MOVQ runtime·m0+m_tls(SB), AX 58 CMPQ AX, $0x123 59 JEQ 2(PC) 60 CALL runtime·abort(SB) 61 ok: 62 // set the per-goroutine and per-mach "registers" 63 get_tls(BX) 64 LEAL runtime·g0(SB), CX 65 MOVL CX, g(BX) 66 LEAL runtime·m0(SB), AX 67 68 // save m->g0 = g0 69 MOVL CX, m_g0(AX) 70 // save m0 to g0->m 71 MOVL AX, g_m(CX) 72 73 CLD // convention is D is always left cleared 74 CALL runtime·check(SB) 75 76 MOVL 16(SP), AX // copy argc 77 MOVL AX, 0(SP) 78 MOVL 24(SP), AX // copy argv 79 MOVL AX, 4(SP) 80 CALL runtime·args(SB) 81 CALL runtime·osinit(SB) 82 CALL runtime·schedinit(SB) 83 84 // create a new goroutine to start program 85 MOVL $runtime·mainPC(SB), AX // entry 86 MOVL $0, 0(SP) 87 MOVL AX, 4(SP) 88 CALL runtime·newproc(SB) 89 90 // start this M 91 CALL runtime·mstart(SB) 92 93 MOVL $0xf1, 0xf1 // crash 94 RET 95 96 DATA runtime·mainPC+0(SB)/4,$runtime·main(SB) 97 GLOBL runtime·mainPC(SB),RODATA,$4 98 99 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 100 INT $3 101 RET 102 103 TEXT runtime·asminit(SB),NOSPLIT,$0-0 104 // No per-thread init. 105 RET 106 107 /* 108 * go-routine 109 */ 110 111 // void gosave(Gobuf*) 112 // save state in Gobuf; setjmp 113 TEXT runtime·gosave(SB), NOSPLIT, $0-4 114 MOVL buf+0(FP), AX // gobuf 115 LEAL buf+0(FP), BX // caller's SP 116 MOVL BX, gobuf_sp(AX) 117 MOVL 0(SP), BX // caller's PC 118 MOVL BX, gobuf_pc(AX) 119 MOVQ $0, gobuf_ret(AX) 120 // Assert ctxt is zero. See func save. 121 MOVL gobuf_ctxt(AX), BX 122 TESTL BX, BX 123 JZ 2(PC) 124 CALL runtime·badctxt(SB) 125 get_tls(CX) 126 MOVL g(CX), BX 127 MOVL BX, gobuf_g(AX) 128 RET 129 130 // void gogo(Gobuf*) 131 // restore state from Gobuf; longjmp 132 TEXT runtime·gogo(SB), NOSPLIT, $8-4 133 MOVL buf+0(FP), BX // gobuf 134 MOVL gobuf_g(BX), DX 135 MOVL 0(DX), CX // make sure g != nil 136 get_tls(CX) 137 MOVL DX, g(CX) 138 MOVL gobuf_sp(BX), SP // restore SP 139 MOVL gobuf_ctxt(BX), DX 140 MOVQ gobuf_ret(BX), AX 141 MOVL $0, gobuf_sp(BX) // clear to help garbage collector 142 MOVQ $0, gobuf_ret(BX) 143 MOVL $0, gobuf_ctxt(BX) 144 MOVL gobuf_pc(BX), BX 145 JMP BX 146 147 // func mcall(fn func(*g)) 148 // Switch to m->g0's stack, call fn(g). 149 // Fn must never return. It should gogo(&g->sched) 150 // to keep running g. 151 TEXT runtime·mcall(SB), NOSPLIT, $0-4 152 MOVL fn+0(FP), DI 153 154 get_tls(CX) 155 MOVL g(CX), AX // save state in g->sched 156 MOVL 0(SP), BX // caller's PC 157 MOVL BX, (g_sched+gobuf_pc)(AX) 158 LEAL fn+0(FP), BX // caller's SP 159 MOVL BX, (g_sched+gobuf_sp)(AX) 160 MOVL AX, (g_sched+gobuf_g)(AX) 161 162 // switch to m->g0 & its stack, call fn 163 MOVL g(CX), BX 164 MOVL g_m(BX), BX 165 MOVL m_g0(BX), SI 166 CMPL SI, AX // if g == m->g0 call badmcall 167 JNE 3(PC) 168 MOVL $runtime·badmcall(SB), AX 169 JMP AX 170 MOVL SI, g(CX) // g = m->g0 171 MOVL (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp 172 PUSHQ AX 173 MOVL DI, DX 174 MOVL 0(DI), DI 175 CALL DI 176 POPQ AX 177 MOVL $runtime·badmcall2(SB), AX 178 JMP AX 179 RET 180 181 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 182 // of the G stack. We need to distinguish the routine that 183 // lives at the bottom of the G stack from the one that lives 184 // at the top of the system stack because the one at the top of 185 // the system stack terminates the stack walk (see topofstack()). 186 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 187 RET 188 189 // func systemstack(fn func()) 190 TEXT runtime·systemstack(SB), NOSPLIT, $0-4 191 MOVL fn+0(FP), DI // DI = fn 192 get_tls(CX) 193 MOVL g(CX), AX // AX = g 194 MOVL g_m(AX), BX // BX = m 195 196 CMPL AX, m_gsignal(BX) 197 JEQ noswitch 198 199 MOVL m_g0(BX), DX // DX = g0 200 CMPL AX, DX 201 JEQ noswitch 202 203 CMPL AX, m_curg(BX) 204 JNE bad 205 206 // switch stacks 207 // save our state in g->sched. Pretend to 208 // be systemstack_switch if the G stack is scanned. 209 MOVL $runtime·systemstack_switch(SB), SI 210 MOVL SI, (g_sched+gobuf_pc)(AX) 211 MOVL SP, (g_sched+gobuf_sp)(AX) 212 MOVL AX, (g_sched+gobuf_g)(AX) 213 214 // switch to g0 215 MOVL DX, g(CX) 216 MOVL (g_sched+gobuf_sp)(DX), SP 217 218 // call target function 219 MOVL DI, DX 220 MOVL 0(DI), DI 221 CALL DI 222 223 // switch back to g 224 get_tls(CX) 225 MOVL g(CX), AX 226 MOVL g_m(AX), BX 227 MOVL m_curg(BX), AX 228 MOVL AX, g(CX) 229 MOVL (g_sched+gobuf_sp)(AX), SP 230 MOVL $0, (g_sched+gobuf_sp)(AX) 231 RET 232 233 noswitch: 234 // already on m stack, just call directly 235 // Using a tail call here cleans up tracebacks since we won't stop 236 // at an intermediate systemstack. 237 MOVL DI, DX 238 MOVL 0(DI), DI 239 JMP DI 240 241 bad: 242 // Not g0, not curg. Must be gsignal, but that's not allowed. 243 // Hide call from linker nosplit analysis. 244 MOVL $runtime·badsystemstack(SB), AX 245 CALL AX 246 INT $3 247 248 /* 249 * support for morestack 250 */ 251 252 // Called during function prolog when more stack is needed. 253 // 254 // The traceback routines see morestack on a g0 as being 255 // the top of a stack (for example, morestack calling newstack 256 // calling the scheduler calling newm calling gc), so we must 257 // record an argument size. For that purpose, it has no arguments. 258 TEXT runtime·morestack(SB),NOSPLIT,$0-0 259 get_tls(CX) 260 MOVL g(CX), BX 261 MOVL g_m(BX), BX 262 263 // Cannot grow scheduler stack (m->g0). 264 MOVL m_g0(BX), SI 265 CMPL g(CX), SI 266 JNE 3(PC) 267 CALL runtime·badmorestackg0(SB) 268 MOVL 0, AX 269 270 // Cannot grow signal stack (m->gsignal). 271 MOVL m_gsignal(BX), SI 272 CMPL g(CX), SI 273 JNE 3(PC) 274 CALL runtime·badmorestackgsignal(SB) 275 MOVL 0, AX 276 277 // Called from f. 278 // Set m->morebuf to f's caller. 279 MOVL 8(SP), AX // f's caller's PC 280 MOVL AX, (m_morebuf+gobuf_pc)(BX) 281 LEAL 16(SP), AX // f's caller's SP 282 MOVL AX, (m_morebuf+gobuf_sp)(BX) 283 get_tls(CX) 284 MOVL g(CX), SI 285 MOVL SI, (m_morebuf+gobuf_g)(BX) 286 287 // Set g->sched to context in f. 288 MOVL 0(SP), AX // f's PC 289 MOVL AX, (g_sched+gobuf_pc)(SI) 290 MOVL SI, (g_sched+gobuf_g)(SI) 291 LEAL 8(SP), AX // f's SP 292 MOVL AX, (g_sched+gobuf_sp)(SI) 293 MOVL DX, (g_sched+gobuf_ctxt)(SI) 294 295 // Call newstack on m->g0's stack. 296 MOVL m_g0(BX), BX 297 MOVL BX, g(CX) 298 MOVL (g_sched+gobuf_sp)(BX), SP 299 CALL runtime·newstack(SB) 300 MOVL $0, 0x1003 // crash if newstack returns 301 RET 302 303 // morestack trampolines 304 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0 305 MOVL $0, DX 306 JMP runtime·morestack(SB) 307 308 // reflectcall: call a function with the given argument list 309 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 310 // we don't have variable-sized frames, so we use a small number 311 // of constant-sized-frame functions to encode a few bits of size in the pc. 312 // Caution: ugly multiline assembly macros in your future! 313 314 #define DISPATCH(NAME,MAXSIZE) \ 315 CMPL CX, $MAXSIZE; \ 316 JA 3(PC); \ 317 MOVL $NAME(SB), AX; \ 318 JMP AX 319 // Note: can't just "JMP NAME(SB)" - bad inlining results. 320 321 TEXT ·reflectcall(SB), NOSPLIT, $0-20 322 MOVLQZX argsize+12(FP), CX 323 DISPATCH(runtime·call16, 16) 324 DISPATCH(runtime·call32, 32) 325 DISPATCH(runtime·call64, 64) 326 DISPATCH(runtime·call128, 128) 327 DISPATCH(runtime·call256, 256) 328 DISPATCH(runtime·call512, 512) 329 DISPATCH(runtime·call1024, 1024) 330 DISPATCH(runtime·call2048, 2048) 331 DISPATCH(runtime·call4096, 4096) 332 DISPATCH(runtime·call8192, 8192) 333 DISPATCH(runtime·call16384, 16384) 334 DISPATCH(runtime·call32768, 32768) 335 DISPATCH(runtime·call65536, 65536) 336 DISPATCH(runtime·call131072, 131072) 337 DISPATCH(runtime·call262144, 262144) 338 DISPATCH(runtime·call524288, 524288) 339 DISPATCH(runtime·call1048576, 1048576) 340 DISPATCH(runtime·call2097152, 2097152) 341 DISPATCH(runtime·call4194304, 4194304) 342 DISPATCH(runtime·call8388608, 8388608) 343 DISPATCH(runtime·call16777216, 16777216) 344 DISPATCH(runtime·call33554432, 33554432) 345 DISPATCH(runtime·call67108864, 67108864) 346 DISPATCH(runtime·call134217728, 134217728) 347 DISPATCH(runtime·call268435456, 268435456) 348 DISPATCH(runtime·call536870912, 536870912) 349 DISPATCH(runtime·call1073741824, 1073741824) 350 MOVL $runtime·badreflectcall(SB), AX 351 JMP AX 352 353 #define CALLFN(NAME,MAXSIZE) \ 354 TEXT NAME(SB), WRAPPER, $MAXSIZE-20; \ 355 NO_LOCAL_POINTERS; \ 356 /* copy arguments to stack */ \ 357 MOVL argptr+8(FP), SI; \ 358 MOVL argsize+12(FP), CX; \ 359 MOVL SP, DI; \ 360 REP;MOVSB; \ 361 /* call function */ \ 362 MOVL f+4(FP), DX; \ 363 MOVL (DX), AX; \ 364 CALL AX; \ 365 /* copy return values back */ \ 366 MOVL argtype+0(FP), DX; \ 367 MOVL argptr+8(FP), DI; \ 368 MOVL argsize+12(FP), CX; \ 369 MOVL retoffset+16(FP), BX; \ 370 MOVL SP, SI; \ 371 ADDL BX, DI; \ 372 ADDL BX, SI; \ 373 SUBL BX, CX; \ 374 CALL callRet<>(SB); \ 375 RET 376 377 // callRet copies return values back at the end of call*. This is a 378 // separate function so it can allocate stack space for the arguments 379 // to reflectcallmove. It does not follow the Go ABI; it expects its 380 // arguments in registers. 381 TEXT callRet<>(SB), NOSPLIT, $16-0 382 MOVL DX, 0(SP) 383 MOVL DI, 4(SP) 384 MOVL SI, 8(SP) 385 MOVL CX, 12(SP) 386 CALL runtime·reflectcallmove(SB) 387 RET 388 389 CALLFN(·call16, 16) 390 CALLFN(·call32, 32) 391 CALLFN(·call64, 64) 392 CALLFN(·call128, 128) 393 CALLFN(·call256, 256) 394 CALLFN(·call512, 512) 395 CALLFN(·call1024, 1024) 396 CALLFN(·call2048, 2048) 397 CALLFN(·call4096, 4096) 398 CALLFN(·call8192, 8192) 399 CALLFN(·call16384, 16384) 400 CALLFN(·call32768, 32768) 401 CALLFN(·call65536, 65536) 402 CALLFN(·call131072, 131072) 403 CALLFN(·call262144, 262144) 404 CALLFN(·call524288, 524288) 405 CALLFN(·call1048576, 1048576) 406 CALLFN(·call2097152, 2097152) 407 CALLFN(·call4194304, 4194304) 408 CALLFN(·call8388608, 8388608) 409 CALLFN(·call16777216, 16777216) 410 CALLFN(·call33554432, 33554432) 411 CALLFN(·call67108864, 67108864) 412 CALLFN(·call134217728, 134217728) 413 CALLFN(·call268435456, 268435456) 414 CALLFN(·call536870912, 536870912) 415 CALLFN(·call1073741824, 1073741824) 416 417 TEXT runtime·procyield(SB),NOSPLIT,$0-0 418 MOVL cycles+0(FP), AX 419 again: 420 PAUSE 421 SUBL $1, AX 422 JNZ again 423 RET 424 425 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 426 // Stores are already ordered on x86, so this is just a 427 // compile barrier. 428 RET 429 430 // void jmpdefer(fn, sp); 431 // called from deferreturn. 432 // 1. pop the caller 433 // 2. sub 5 bytes from the callers return 434 // 3. jmp to the argument 435 TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 436 MOVL fv+0(FP), DX 437 MOVL argp+4(FP), BX 438 LEAL -8(BX), SP // caller sp after CALL 439 SUBL $5, (SP) // return to CALL again 440 MOVL 0(DX), BX 441 JMP BX // but first run the deferred function 442 443 // func asmcgocall(fn, arg unsafe.Pointer) int32 444 // Not implemented. 445 TEXT runtime·asmcgocall(SB),NOSPLIT,$0-12 446 MOVL 0, AX 447 RET 448 449 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize) 450 // Not implemented. 451 TEXT runtime·cgocallback(SB),NOSPLIT,$0-16 452 MOVL 0, AX 453 RET 454 455 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize) 456 // Not implemented. 457 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$0-16 458 MOVL 0, AX 459 RET 460 461 // void setg(G*); set g. for use by needm. 462 // Not implemented. 463 TEXT runtime·setg(SB), NOSPLIT, $0-4 464 MOVL 0, AX 465 RET 466 467 TEXT runtime·abort(SB),NOSPLIT,$0-0 468 INT $3 469 loop: 470 JMP loop 471 472 // check that SP is in range [g->stack.lo, g->stack.hi) 473 TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 474 get_tls(CX) 475 MOVL g(CX), AX 476 CMPL (g_stack+stack_hi)(AX), SP 477 JHI 2(PC) 478 MOVL 0, AX 479 CMPL SP, (g_stack+stack_lo)(AX) 480 JHI 2(PC) 481 MOVL 0, AX 482 RET 483 484 // int64 runtime·cputicks(void) 485 TEXT runtime·cputicks(SB),NOSPLIT,$0-0 486 RDTSC 487 SHLQ $32, DX 488 ADDQ DX, AX 489 MOVQ AX, ret+0(FP) 490 RET 491 492 // hash function using AES hardware instructions 493 // For now, our one amd64p32 system (NaCl) does not 494 // support using AES instructions, so have not bothered to 495 // write the implementations. Can copy and adjust the ones 496 // in asm_amd64.s when the time comes. 497 498 TEXT runtime·aeshash(SB),NOSPLIT,$0-20 499 MOVL AX, ret+16(FP) 500 RET 501 502 TEXT runtime·aeshashstr(SB),NOSPLIT,$0-12 503 MOVL AX, ret+8(FP) 504 RET 505 506 TEXT runtime·aeshash32(SB),NOSPLIT,$0-12 507 MOVL AX, ret+8(FP) 508 RET 509 510 TEXT runtime·aeshash64(SB),NOSPLIT,$0-12 511 MOVL AX, ret+8(FP) 512 RET 513 514 TEXT runtime·return0(SB), NOSPLIT, $0 515 MOVL $0, AX 516 RET 517 518 // The top-most function running on a goroutine 519 // returns to goexit+PCQuantum. 520 TEXT runtime·goexit(SB),NOSPLIT,$0-0 521 BYTE $0x90 // NOP 522 CALL runtime·goexit1(SB) // does not return 523 // traceback from goexit1 must hit code range of goexit 524 BYTE $0x90 // NOP 525 526 TEXT ·checkASM(SB),NOSPLIT,$0-1 527 MOVB $1, ret+0(FP) 528 RET 529 530 // gcWriteBarrier performs a heap pointer write and informs the GC. 531 // 532 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 533 // - DI is the destination of the write 534 // - AX is the value being written at DI 535 // It clobbers FLAGS and SI. It does not clobber any other general-purpose registers, 536 // but may clobber others (e.g., SSE registers). 537 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$88 538 // Save the registers clobbered by the fast path. This is slightly 539 // faster than having the caller spill these. 540 MOVQ R14, 72(SP) 541 MOVQ R13, 80(SP) 542 // TODO: Consider passing g.m.p in as an argument so they can be shared 543 // across a sequence of write barriers. 544 get_tls(R13) 545 MOVL g(R13), R13 546 MOVL g_m(R13), R13 547 MOVL m_p(R13), R13 548 MOVL (p_wbBuf+wbBuf_next)(R13), R14 549 // Increment wbBuf.next position. 550 LEAL 8(R14), R14 551 MOVL R14, (p_wbBuf+wbBuf_next)(R13) 552 CMPL R14, (p_wbBuf+wbBuf_end)(R13) 553 // Record the write. 554 MOVL AX, -8(R14) // Record value 555 MOVL (DI), R13 // TODO: This turns bad writes into bad reads. 556 MOVL R13, -4(R14) // Record *slot 557 // Is the buffer full? (flags set in CMPL above) 558 JEQ flush 559 ret: 560 MOVQ 72(SP), R14 561 MOVQ 80(SP), R13 562 // Do the write. 563 MOVL AX, (DI) 564 RET // Clobbers SI on NaCl 565 566 flush: 567 // Save all general purpose registers since these could be 568 // clobbered by wbBufFlush and were not saved by the caller. 569 // It is possible for wbBufFlush to clobber other registers 570 // (e.g., SSE registers), but the compiler takes care of saving 571 // those in the caller if necessary. This strikes a balance 572 // with registers that are likely to be used. 573 // 574 // We don't have type information for these, but all code under 575 // here is NOSPLIT, so nothing will observe these. 576 // 577 // TODO: We could strike a different balance; e.g., saving X0 578 // and not saving GP registers that are less likely to be used. 579 MOVL DI, 0(SP) // Also first argument to wbBufFlush 580 MOVL AX, 4(SP) // Also second argument to wbBufFlush 581 MOVQ BX, 8(SP) 582 MOVQ CX, 16(SP) 583 MOVQ DX, 24(SP) 584 // DI already saved 585 // SI is always clobbered on nacl 586 // BP is reserved on nacl 587 MOVQ R8, 32(SP) 588 MOVQ R9, 40(SP) 589 MOVQ R10, 48(SP) 590 MOVQ R11, 56(SP) 591 MOVQ R12, 64(SP) 592 // R13 already saved 593 // R14 already saved 594 // R15 is reserved on nacl 595 596 // This takes arguments DI and AX 597 CALL runtime·wbBufFlush(SB) 598 599 MOVL 0(SP), DI 600 MOVL 4(SP), AX 601 MOVQ 8(SP), BX 602 MOVQ 16(SP), CX 603 MOVQ 24(SP), DX 604 MOVQ 32(SP), R8 605 MOVQ 40(SP), R9 606 MOVQ 48(SP), R10 607 MOVQ 56(SP), R11 608 MOVQ 64(SP), R12 609 JMP ret