github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/runtime/asm_386.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 // _rt0_386 is common startup code for most 386 systems when using 11 // internal linking. This is the entry point for the program from the 12 // kernel for an ordinary -buildmode=exe program. The stack holds the 13 // number of arguments and the C-style argv. 14 TEXT _rt0_386(SB),NOSPLIT,$8 15 MOVL 8(SP), AX // argc 16 LEAL 12(SP), BX // argv 17 MOVL AX, 0(SP) 18 MOVL BX, 4(SP) 19 JMP runtime·rt0_go(SB) 20 21 // _rt0_386_lib is common startup code for most 386 systems when 22 // using -buildmode=c-archive or -buildmode=c-shared. The linker will 23 // arrange to invoke this function as a global constructor (for 24 // c-archive) or when the shared library is loaded (for c-shared). 25 // We expect argc and argv to be passed on the stack following the 26 // usual C ABI. 27 TEXT _rt0_386_lib(SB),NOSPLIT,$0 28 PUSHL BP 29 MOVL SP, BP 30 PUSHL BX 31 PUSHL SI 32 PUSHL DI 33 34 MOVL 8(BP), AX 35 MOVL AX, _rt0_386_lib_argc<>(SB) 36 MOVL 12(BP), AX 37 MOVL AX, _rt0_386_lib_argv<>(SB) 38 39 // Synchronous initialization. 40 CALL runtime·libpreinit(SB) 41 42 SUBL $8, SP 43 44 // Create a new thread to do the runtime initialization. 45 MOVL _cgo_sys_thread_create(SB), AX 46 TESTL AX, AX 47 JZ nocgo 48 49 // Align stack to call C function. 50 // We moved SP to BP above, but BP was clobbered by the libpreinit call. 51 MOVL SP, BP 52 ANDL $~15, SP 53 54 MOVL $_rt0_386_lib_go(SB), BX 55 MOVL BX, 0(SP) 56 MOVL $0, 4(SP) 57 58 CALL AX 59 60 MOVL BP, SP 61 62 JMP restore 63 64 nocgo: 65 MOVL $0x800000, 0(SP) // stacksize = 8192KB 66 MOVL $_rt0_386_lib_go(SB), AX 67 MOVL AX, 4(SP) // fn 68 CALL runtime·newosproc0(SB) 69 70 restore: 71 ADDL $8, SP 72 POPL DI 73 POPL SI 74 POPL BX 75 POPL BP 76 RET 77 78 // _rt0_386_lib_go initializes the Go runtime. 79 // This is started in a separate thread by _rt0_386_lib. 80 TEXT _rt0_386_lib_go(SB),NOSPLIT,$8 81 MOVL _rt0_386_lib_argc<>(SB), AX 82 MOVL AX, 0(SP) 83 MOVL _rt0_386_lib_argv<>(SB), AX 84 MOVL AX, 4(SP) 85 JMP runtime·rt0_go(SB) 86 87 DATA _rt0_386_lib_argc<>(SB)/4, $0 88 GLOBL _rt0_386_lib_argc<>(SB),NOPTR, $4 89 DATA _rt0_386_lib_argv<>(SB)/4, $0 90 GLOBL _rt0_386_lib_argv<>(SB),NOPTR, $4 91 92 TEXT runtime·rt0_go(SB),NOSPLIT,$0 93 // Copy arguments forward on an even stack. 94 // Users of this function jump to it, they don't call it. 95 MOVL 0(SP), AX 96 MOVL 4(SP), BX 97 SUBL $128, SP // plenty of scratch 98 ANDL $~15, SP 99 MOVL AX, 120(SP) // save argc, argv away 100 MOVL BX, 124(SP) 101 102 // set default stack bounds. 103 // _cgo_init may update stackguard. 104 MOVL $runtime·g0(SB), BP 105 LEAL (-64*1024+104)(SP), BX 106 MOVL BX, g_stackguard0(BP) 107 MOVL BX, g_stackguard1(BP) 108 MOVL BX, (g_stack+stack_lo)(BP) 109 MOVL SP, (g_stack+stack_hi)(BP) 110 111 // find out information about the processor we're on 112 #ifdef GOOS_nacl // NaCl doesn't like PUSHFL/POPFL 113 JMP has_cpuid 114 #else 115 // first see if CPUID instruction is supported. 116 PUSHFL 117 PUSHFL 118 XORL $(1<<21), 0(SP) // flip ID bit 119 POPFL 120 PUSHFL 121 POPL AX 122 XORL 0(SP), AX 123 POPFL // restore EFLAGS 124 TESTL $(1<<21), AX 125 JNE has_cpuid 126 #endif 127 128 bad_proc: // show that the program requires MMX. 129 MOVL $2, 0(SP) 130 MOVL $bad_proc_msg<>(SB), 4(SP) 131 MOVL $0x3d, 8(SP) 132 CALL runtime·write(SB) 133 MOVL $1, 0(SP) 134 CALL runtime·exit(SB) 135 CALL runtime·abort(SB) 136 137 has_cpuid: 138 MOVL $0, AX 139 CPUID 140 MOVL AX, SI 141 CMPL AX, $0 142 JE nocpuinfo 143 144 // Figure out how to serialize RDTSC. 145 // On Intel processors LFENCE is enough. AMD requires MFENCE. 146 // Don't know about the rest, so let's do MFENCE. 147 CMPL BX, $0x756E6547 // "Genu" 148 JNE notintel 149 CMPL DX, $0x49656E69 // "ineI" 150 JNE notintel 151 CMPL CX, $0x6C65746E // "ntel" 152 JNE notintel 153 MOVB $1, runtime·isIntel(SB) 154 MOVB $1, runtime·lfenceBeforeRdtsc(SB) 155 notintel: 156 157 // Load EAX=1 cpuid flags 158 MOVL $1, AX 159 CPUID 160 MOVL CX, DI // Move to global variable clobbers CX when generating PIC 161 MOVL AX, runtime·processorVersionInfo(SB) 162 163 // Check for MMX support 164 TESTL $(1<<23), DX // MMX 165 JZ bad_proc 166 167 nocpuinfo: 168 // if there is an _cgo_init, call it to let it 169 // initialize and to set up GS. if not, 170 // we set up GS ourselves. 171 MOVL _cgo_init(SB), AX 172 TESTL AX, AX 173 JZ needtls 174 MOVL $setg_gcc<>(SB), BX 175 MOVL BX, 4(SP) 176 MOVL BP, 0(SP) 177 CALL AX 178 179 // update stackguard after _cgo_init 180 MOVL $runtime·g0(SB), CX 181 MOVL (g_stack+stack_lo)(CX), AX 182 ADDL $const__StackGuard, AX 183 MOVL AX, g_stackguard0(CX) 184 MOVL AX, g_stackguard1(CX) 185 186 #ifndef GOOS_windows 187 // skip runtime·ldt0setup(SB) and tls test after _cgo_init for non-windows 188 JMP ok 189 #endif 190 needtls: 191 #ifdef GOOS_plan9 192 // skip runtime·ldt0setup(SB) and tls test on Plan 9 in all cases 193 JMP ok 194 #endif 195 #ifdef GOOS_darwin 196 // skip runtime·ldt0setup(SB) on Darwin 197 JMP ok 198 #endif 199 200 // set up %gs 201 CALL runtime·ldt0setup(SB) 202 203 // store through it, to make sure it works 204 get_tls(BX) 205 MOVL $0x123, g(BX) 206 MOVL runtime·m0+m_tls(SB), AX 207 CMPL AX, $0x123 208 JEQ ok 209 MOVL AX, 0 // abort 210 ok: 211 // set up m and g "registers" 212 get_tls(BX) 213 LEAL runtime·g0(SB), DX 214 MOVL DX, g(BX) 215 LEAL runtime·m0(SB), AX 216 217 // save m->g0 = g0 218 MOVL DX, m_g0(AX) 219 // save g0->m = m0 220 MOVL AX, g_m(DX) 221 222 CALL runtime·emptyfunc(SB) // fault if stack check is wrong 223 224 // convention is D is always cleared 225 CLD 226 227 CALL runtime·check(SB) 228 229 // saved argc, argv 230 MOVL 120(SP), AX 231 MOVL AX, 0(SP) 232 MOVL 124(SP), AX 233 MOVL AX, 4(SP) 234 CALL runtime·args(SB) 235 CALL runtime·osinit(SB) 236 CALL runtime·schedinit(SB) 237 238 // create a new goroutine to start program 239 PUSHL $runtime·mainPC(SB) // entry 240 PUSHL $0 // arg size 241 CALL runtime·newproc(SB) 242 POPL AX 243 POPL AX 244 245 // start this M 246 CALL runtime·mstart(SB) 247 248 CALL runtime·abort(SB) 249 RET 250 251 DATA bad_proc_msg<>+0x00(SB)/8, $"This pro" 252 DATA bad_proc_msg<>+0x08(SB)/8, $"gram can" 253 DATA bad_proc_msg<>+0x10(SB)/8, $" only be" 254 DATA bad_proc_msg<>+0x18(SB)/8, $" run on " 255 DATA bad_proc_msg<>+0x20(SB)/8, $"processo" 256 DATA bad_proc_msg<>+0x28(SB)/8, $"rs with " 257 DATA bad_proc_msg<>+0x30(SB)/8, $"MMX supp" 258 DATA bad_proc_msg<>+0x38(SB)/4, $"ort." 259 DATA bad_proc_msg<>+0x3c(SB)/1, $0xa 260 GLOBL bad_proc_msg<>(SB), RODATA, $0x3d 261 262 DATA runtime·mainPC+0(SB)/4,$runtime·main(SB) 263 GLOBL runtime·mainPC(SB),RODATA,$4 264 265 TEXT runtime·breakpoint(SB),NOSPLIT,$0-0 266 INT $3 267 RET 268 269 TEXT runtime·asminit(SB),NOSPLIT,$0-0 270 // Linux and MinGW start the FPU in extended double precision. 271 // Other operating systems use double precision. 272 // Change to double precision to match them, 273 // and to match other hardware that only has double. 274 FLDCW runtime·controlWord64(SB) 275 RET 276 277 /* 278 * go-routine 279 */ 280 281 // void gosave(Gobuf*) 282 // save state in Gobuf; setjmp 283 TEXT runtime·gosave(SB), NOSPLIT, $0-4 284 MOVL buf+0(FP), AX // gobuf 285 LEAL buf+0(FP), BX // caller's SP 286 MOVL BX, gobuf_sp(AX) 287 MOVL 0(SP), BX // caller's PC 288 MOVL BX, gobuf_pc(AX) 289 MOVL $0, gobuf_ret(AX) 290 // Assert ctxt is zero. See func save. 291 MOVL gobuf_ctxt(AX), BX 292 TESTL BX, BX 293 JZ 2(PC) 294 CALL runtime·badctxt(SB) 295 get_tls(CX) 296 MOVL g(CX), BX 297 MOVL BX, gobuf_g(AX) 298 RET 299 300 // void gogo(Gobuf*) 301 // restore state from Gobuf; longjmp 302 TEXT runtime·gogo(SB), NOSPLIT, $8-4 303 MOVL buf+0(FP), BX // gobuf 304 MOVL gobuf_g(BX), DX 305 MOVL 0(DX), CX // make sure g != nil 306 get_tls(CX) 307 MOVL DX, g(CX) 308 MOVL gobuf_sp(BX), SP // restore SP 309 MOVL gobuf_ret(BX), AX 310 MOVL gobuf_ctxt(BX), DX 311 MOVL $0, gobuf_sp(BX) // clear to help garbage collector 312 MOVL $0, gobuf_ret(BX) 313 MOVL $0, gobuf_ctxt(BX) 314 MOVL gobuf_pc(BX), BX 315 JMP BX 316 317 // func mcall(fn func(*g)) 318 // Switch to m->g0's stack, call fn(g). 319 // Fn must never return. It should gogo(&g->sched) 320 // to keep running g. 321 TEXT runtime·mcall(SB), NOSPLIT, $0-4 322 MOVL fn+0(FP), DI 323 324 get_tls(DX) 325 MOVL g(DX), AX // save state in g->sched 326 MOVL 0(SP), BX // caller's PC 327 MOVL BX, (g_sched+gobuf_pc)(AX) 328 LEAL fn+0(FP), BX // caller's SP 329 MOVL BX, (g_sched+gobuf_sp)(AX) 330 MOVL AX, (g_sched+gobuf_g)(AX) 331 332 // switch to m->g0 & its stack, call fn 333 MOVL g(DX), BX 334 MOVL g_m(BX), BX 335 MOVL m_g0(BX), SI 336 CMPL SI, AX // if g == m->g0 call badmcall 337 JNE 3(PC) 338 MOVL $runtime·badmcall(SB), AX 339 JMP AX 340 MOVL SI, g(DX) // g = m->g0 341 MOVL (g_sched+gobuf_sp)(SI), SP // sp = m->g0->sched.sp 342 PUSHL AX 343 MOVL DI, DX 344 MOVL 0(DI), DI 345 CALL DI 346 POPL AX 347 MOVL $runtime·badmcall2(SB), AX 348 JMP AX 349 RET 350 351 // systemstack_switch is a dummy routine that systemstack leaves at the bottom 352 // of the G stack. We need to distinguish the routine that 353 // lives at the bottom of the G stack from the one that lives 354 // at the top of the system stack because the one at the top of 355 // the system stack terminates the stack walk (see topofstack()). 356 TEXT runtime·systemstack_switch(SB), NOSPLIT, $0-0 357 RET 358 359 // func systemstack(fn func()) 360 TEXT runtime·systemstack(SB), NOSPLIT, $0-4 361 MOVL fn+0(FP), DI // DI = fn 362 get_tls(CX) 363 MOVL g(CX), AX // AX = g 364 MOVL g_m(AX), BX // BX = m 365 366 CMPL AX, m_gsignal(BX) 367 JEQ noswitch 368 369 MOVL m_g0(BX), DX // DX = g0 370 CMPL AX, DX 371 JEQ noswitch 372 373 CMPL AX, m_curg(BX) 374 JNE bad 375 376 // switch stacks 377 // save our state in g->sched. Pretend to 378 // be systemstack_switch if the G stack is scanned. 379 MOVL $runtime·systemstack_switch(SB), (g_sched+gobuf_pc)(AX) 380 MOVL SP, (g_sched+gobuf_sp)(AX) 381 MOVL AX, (g_sched+gobuf_g)(AX) 382 383 // switch to g0 384 get_tls(CX) 385 MOVL DX, g(CX) 386 MOVL (g_sched+gobuf_sp)(DX), BX 387 // make it look like mstart called systemstack on g0, to stop traceback 388 SUBL $4, BX 389 MOVL $runtime·mstart(SB), DX 390 MOVL DX, 0(BX) 391 MOVL BX, SP 392 393 // call target function 394 MOVL DI, DX 395 MOVL 0(DI), DI 396 CALL DI 397 398 // switch back to g 399 get_tls(CX) 400 MOVL g(CX), AX 401 MOVL g_m(AX), BX 402 MOVL m_curg(BX), AX 403 MOVL AX, g(CX) 404 MOVL (g_sched+gobuf_sp)(AX), SP 405 MOVL $0, (g_sched+gobuf_sp)(AX) 406 RET 407 408 noswitch: 409 // already on system stack; tail call the function 410 // Using a tail call here cleans up tracebacks since we won't stop 411 // at an intermediate systemstack. 412 MOVL DI, DX 413 MOVL 0(DI), DI 414 JMP DI 415 416 bad: 417 // Bad: g is not gsignal, not g0, not curg. What is it? 418 // Hide call from linker nosplit analysis. 419 MOVL $runtime·badsystemstack(SB), AX 420 CALL AX 421 INT $3 422 423 /* 424 * support for morestack 425 */ 426 427 // Called during function prolog when more stack is needed. 428 // 429 // The traceback routines see morestack on a g0 as being 430 // the top of a stack (for example, morestack calling newstack 431 // calling the scheduler calling newm calling gc), so we must 432 // record an argument size. For that purpose, it has no arguments. 433 TEXT runtime·morestack(SB),NOSPLIT,$0-0 434 // Cannot grow scheduler stack (m->g0). 435 get_tls(CX) 436 MOVL g(CX), BX 437 MOVL g_m(BX), BX 438 MOVL m_g0(BX), SI 439 CMPL g(CX), SI 440 JNE 3(PC) 441 CALL runtime·badmorestackg0(SB) 442 CALL runtime·abort(SB) 443 444 // Cannot grow signal stack. 445 MOVL m_gsignal(BX), SI 446 CMPL g(CX), SI 447 JNE 3(PC) 448 CALL runtime·badmorestackgsignal(SB) 449 CALL runtime·abort(SB) 450 451 // Called from f. 452 // Set m->morebuf to f's caller. 453 MOVL 4(SP), DI // f's caller's PC 454 MOVL DI, (m_morebuf+gobuf_pc)(BX) 455 LEAL 8(SP), CX // f's caller's SP 456 MOVL CX, (m_morebuf+gobuf_sp)(BX) 457 get_tls(CX) 458 MOVL g(CX), SI 459 MOVL SI, (m_morebuf+gobuf_g)(BX) 460 461 // Set g->sched to context in f. 462 MOVL 0(SP), AX // f's PC 463 MOVL AX, (g_sched+gobuf_pc)(SI) 464 MOVL SI, (g_sched+gobuf_g)(SI) 465 LEAL 4(SP), AX // f's SP 466 MOVL AX, (g_sched+gobuf_sp)(SI) 467 MOVL DX, (g_sched+gobuf_ctxt)(SI) 468 469 // Call newstack on m->g0's stack. 470 MOVL m_g0(BX), BP 471 MOVL BP, g(CX) 472 MOVL (g_sched+gobuf_sp)(BP), AX 473 MOVL -4(AX), BX // fault if CALL would, before smashing SP 474 MOVL AX, SP 475 CALL runtime·newstack(SB) 476 CALL runtime·abort(SB) // crash if newstack returns 477 RET 478 479 TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0-0 480 MOVL $0, DX 481 JMP runtime·morestack(SB) 482 483 // reflectcall: call a function with the given argument list 484 // func call(argtype *_type, f *FuncVal, arg *byte, argsize, retoffset uint32). 485 // we don't have variable-sized frames, so we use a small number 486 // of constant-sized-frame functions to encode a few bits of size in the pc. 487 // Caution: ugly multiline assembly macros in your future! 488 489 #define DISPATCH(NAME,MAXSIZE) \ 490 CMPL CX, $MAXSIZE; \ 491 JA 3(PC); \ 492 MOVL $NAME(SB), AX; \ 493 JMP AX 494 // Note: can't just "JMP NAME(SB)" - bad inlining results. 495 496 TEXT ·reflectcall(SB), NOSPLIT, $0-20 497 MOVL argsize+12(FP), CX 498 DISPATCH(runtime·call16, 16) 499 DISPATCH(runtime·call32, 32) 500 DISPATCH(runtime·call64, 64) 501 DISPATCH(runtime·call128, 128) 502 DISPATCH(runtime·call256, 256) 503 DISPATCH(runtime·call512, 512) 504 DISPATCH(runtime·call1024, 1024) 505 DISPATCH(runtime·call2048, 2048) 506 DISPATCH(runtime·call4096, 4096) 507 DISPATCH(runtime·call8192, 8192) 508 DISPATCH(runtime·call16384, 16384) 509 DISPATCH(runtime·call32768, 32768) 510 DISPATCH(runtime·call65536, 65536) 511 DISPATCH(runtime·call131072, 131072) 512 DISPATCH(runtime·call262144, 262144) 513 DISPATCH(runtime·call524288, 524288) 514 DISPATCH(runtime·call1048576, 1048576) 515 DISPATCH(runtime·call2097152, 2097152) 516 DISPATCH(runtime·call4194304, 4194304) 517 DISPATCH(runtime·call8388608, 8388608) 518 DISPATCH(runtime·call16777216, 16777216) 519 DISPATCH(runtime·call33554432, 33554432) 520 DISPATCH(runtime·call67108864, 67108864) 521 DISPATCH(runtime·call134217728, 134217728) 522 DISPATCH(runtime·call268435456, 268435456) 523 DISPATCH(runtime·call536870912, 536870912) 524 DISPATCH(runtime·call1073741824, 1073741824) 525 MOVL $runtime·badreflectcall(SB), AX 526 JMP AX 527 528 #define CALLFN(NAME,MAXSIZE) \ 529 TEXT NAME(SB), WRAPPER, $MAXSIZE-20; \ 530 NO_LOCAL_POINTERS; \ 531 /* copy arguments to stack */ \ 532 MOVL argptr+8(FP), SI; \ 533 MOVL argsize+12(FP), CX; \ 534 MOVL SP, DI; \ 535 REP;MOVSB; \ 536 /* call function */ \ 537 MOVL f+4(FP), DX; \ 538 MOVL (DX), AX; \ 539 PCDATA $PCDATA_StackMapIndex, $0; \ 540 CALL AX; \ 541 /* copy return values back */ \ 542 MOVL argtype+0(FP), DX; \ 543 MOVL argptr+8(FP), DI; \ 544 MOVL argsize+12(FP), CX; \ 545 MOVL retoffset+16(FP), BX; \ 546 MOVL SP, SI; \ 547 ADDL BX, DI; \ 548 ADDL BX, SI; \ 549 SUBL BX, CX; \ 550 CALL callRet<>(SB); \ 551 RET 552 553 // callRet copies return values back at the end of call*. This is a 554 // separate function so it can allocate stack space for the arguments 555 // to reflectcallmove. It does not follow the Go ABI; it expects its 556 // arguments in registers. 557 TEXT callRet<>(SB), NOSPLIT, $16-0 558 MOVL DX, 0(SP) 559 MOVL DI, 4(SP) 560 MOVL SI, 8(SP) 561 MOVL CX, 12(SP) 562 CALL runtime·reflectcallmove(SB) 563 RET 564 565 CALLFN(·call16, 16) 566 CALLFN(·call32, 32) 567 CALLFN(·call64, 64) 568 CALLFN(·call128, 128) 569 CALLFN(·call256, 256) 570 CALLFN(·call512, 512) 571 CALLFN(·call1024, 1024) 572 CALLFN(·call2048, 2048) 573 CALLFN(·call4096, 4096) 574 CALLFN(·call8192, 8192) 575 CALLFN(·call16384, 16384) 576 CALLFN(·call32768, 32768) 577 CALLFN(·call65536, 65536) 578 CALLFN(·call131072, 131072) 579 CALLFN(·call262144, 262144) 580 CALLFN(·call524288, 524288) 581 CALLFN(·call1048576, 1048576) 582 CALLFN(·call2097152, 2097152) 583 CALLFN(·call4194304, 4194304) 584 CALLFN(·call8388608, 8388608) 585 CALLFN(·call16777216, 16777216) 586 CALLFN(·call33554432, 33554432) 587 CALLFN(·call67108864, 67108864) 588 CALLFN(·call134217728, 134217728) 589 CALLFN(·call268435456, 268435456) 590 CALLFN(·call536870912, 536870912) 591 CALLFN(·call1073741824, 1073741824) 592 593 TEXT runtime·procyield(SB),NOSPLIT,$0-0 594 MOVL cycles+0(FP), AX 595 again: 596 PAUSE 597 SUBL $1, AX 598 JNZ again 599 RET 600 601 TEXT ·publicationBarrier(SB),NOSPLIT,$0-0 602 // Stores are already ordered on x86, so this is just a 603 // compile barrier. 604 RET 605 606 // void jmpdefer(fn, sp); 607 // called from deferreturn. 608 // 1. pop the caller 609 // 2. sub 5 bytes (the length of CALL & a 32 bit displacement) from the callers 610 // return (when building for shared libraries, subtract 16 bytes -- 5 bytes 611 // for CALL & displacement to call __x86.get_pc_thunk.cx, 6 bytes for the 612 // LEAL to load the offset into BX, and finally 5 for the call & displacement) 613 // 3. jmp to the argument 614 TEXT runtime·jmpdefer(SB), NOSPLIT, $0-8 615 MOVL fv+0(FP), DX // fn 616 MOVL argp+4(FP), BX // caller sp 617 LEAL -4(BX), SP // caller sp after CALL 618 #ifdef GOBUILDMODE_shared 619 SUBL $16, (SP) // return to CALL again 620 #else 621 SUBL $5, (SP) // return to CALL again 622 #endif 623 MOVL 0(DX), BX 624 JMP BX // but first run the deferred function 625 626 // Save state of caller into g->sched. 627 TEXT gosave<>(SB),NOSPLIT,$0 628 PUSHL AX 629 PUSHL BX 630 get_tls(BX) 631 MOVL g(BX), BX 632 LEAL arg+0(FP), AX 633 MOVL AX, (g_sched+gobuf_sp)(BX) 634 MOVL -4(AX), AX 635 MOVL AX, (g_sched+gobuf_pc)(BX) 636 MOVL $0, (g_sched+gobuf_ret)(BX) 637 // Assert ctxt is zero. See func save. 638 MOVL (g_sched+gobuf_ctxt)(BX), AX 639 TESTL AX, AX 640 JZ 2(PC) 641 CALL runtime·badctxt(SB) 642 POPL BX 643 POPL AX 644 RET 645 646 // func asmcgocall(fn, arg unsafe.Pointer) int32 647 // Call fn(arg) on the scheduler stack, 648 // aligned appropriately for the gcc ABI. 649 // See cgocall.go for more details. 650 TEXT ·asmcgocall(SB),NOSPLIT,$0-12 651 MOVL fn+0(FP), AX 652 MOVL arg+4(FP), BX 653 654 MOVL SP, DX 655 656 // Figure out if we need to switch to m->g0 stack. 657 // We get called to create new OS threads too, and those 658 // come in on the m->g0 stack already. 659 get_tls(CX) 660 MOVL g(CX), BP 661 CMPL BP, $0 662 JEQ nosave // Don't even have a G yet. 663 MOVL g_m(BP), BP 664 MOVL m_g0(BP), SI 665 MOVL g(CX), DI 666 CMPL SI, DI 667 JEQ noswitch 668 CMPL DI, m_gsignal(BP) 669 JEQ noswitch 670 CALL gosave<>(SB) 671 get_tls(CX) 672 MOVL SI, g(CX) 673 MOVL (g_sched+gobuf_sp)(SI), SP 674 675 noswitch: 676 // Now on a scheduling stack (a pthread-created stack). 677 SUBL $32, SP 678 ANDL $~15, SP // alignment, perhaps unnecessary 679 MOVL DI, 8(SP) // save g 680 MOVL (g_stack+stack_hi)(DI), DI 681 SUBL DX, DI 682 MOVL DI, 4(SP) // save depth in stack (can't just save SP, as stack might be copied during a callback) 683 MOVL BX, 0(SP) // first argument in x86-32 ABI 684 CALL AX 685 686 // Restore registers, g, stack pointer. 687 get_tls(CX) 688 MOVL 8(SP), DI 689 MOVL (g_stack+stack_hi)(DI), SI 690 SUBL 4(SP), SI 691 MOVL DI, g(CX) 692 MOVL SI, SP 693 694 MOVL AX, ret+8(FP) 695 RET 696 nosave: 697 // Now on a scheduling stack (a pthread-created stack). 698 SUBL $32, SP 699 ANDL $~15, SP // alignment, perhaps unnecessary 700 MOVL DX, 4(SP) // save original stack pointer 701 MOVL BX, 0(SP) // first argument in x86-32 ABI 702 CALL AX 703 704 MOVL 4(SP), CX // restore original stack pointer 705 MOVL CX, SP 706 MOVL AX, ret+8(FP) 707 RET 708 709 // cgocallback(void (*fn)(void*), void *frame, uintptr framesize, uintptr ctxt) 710 // Turn the fn into a Go func (by taking its address) and call 711 // cgocallback_gofunc. 712 TEXT runtime·cgocallback(SB),NOSPLIT,$16-16 713 LEAL fn+0(FP), AX 714 MOVL AX, 0(SP) 715 MOVL frame+4(FP), AX 716 MOVL AX, 4(SP) 717 MOVL framesize+8(FP), AX 718 MOVL AX, 8(SP) 719 MOVL ctxt+12(FP), AX 720 MOVL AX, 12(SP) 721 MOVL $runtime·cgocallback_gofunc(SB), AX 722 CALL AX 723 RET 724 725 // cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize, uintptr ctxt) 726 // See cgocall.go for more details. 727 TEXT ·cgocallback_gofunc(SB),NOSPLIT,$12-16 728 NO_LOCAL_POINTERS 729 730 // If g is nil, Go did not create the current thread. 731 // Call needm to obtain one for temporary use. 732 // In this case, we're running on the thread stack, so there's 733 // lots of space, but the linker doesn't know. Hide the call from 734 // the linker analysis by using an indirect call through AX. 735 get_tls(CX) 736 #ifdef GOOS_windows 737 MOVL $0, BP 738 CMPL CX, $0 739 JEQ 2(PC) // TODO 740 #endif 741 MOVL g(CX), BP 742 CMPL BP, $0 743 JEQ needm 744 MOVL g_m(BP), BP 745 MOVL BP, DX // saved copy of oldm 746 JMP havem 747 needm: 748 MOVL $0, 0(SP) 749 MOVL $runtime·needm(SB), AX 750 CALL AX 751 MOVL 0(SP), DX 752 get_tls(CX) 753 MOVL g(CX), BP 754 MOVL g_m(BP), BP 755 756 // Set m->sched.sp = SP, so that if a panic happens 757 // during the function we are about to execute, it will 758 // have a valid SP to run on the g0 stack. 759 // The next few lines (after the havem label) 760 // will save this SP onto the stack and then write 761 // the same SP back to m->sched.sp. That seems redundant, 762 // but if an unrecovered panic happens, unwindm will 763 // restore the g->sched.sp from the stack location 764 // and then systemstack will try to use it. If we don't set it here, 765 // that restored SP will be uninitialized (typically 0) and 766 // will not be usable. 767 MOVL m_g0(BP), SI 768 MOVL SP, (g_sched+gobuf_sp)(SI) 769 770 havem: 771 // Now there's a valid m, and we're running on its m->g0. 772 // Save current m->g0->sched.sp on stack and then set it to SP. 773 // Save current sp in m->g0->sched.sp in preparation for 774 // switch back to m->curg stack. 775 // NOTE: unwindm knows that the saved g->sched.sp is at 0(SP). 776 MOVL m_g0(BP), SI 777 MOVL (g_sched+gobuf_sp)(SI), AX 778 MOVL AX, 0(SP) 779 MOVL SP, (g_sched+gobuf_sp)(SI) 780 781 // Switch to m->curg stack and call runtime.cgocallbackg. 782 // Because we are taking over the execution of m->curg 783 // but *not* resuming what had been running, we need to 784 // save that information (m->curg->sched) so we can restore it. 785 // We can restore m->curg->sched.sp easily, because calling 786 // runtime.cgocallbackg leaves SP unchanged upon return. 787 // To save m->curg->sched.pc, we push it onto the stack. 788 // This has the added benefit that it looks to the traceback 789 // routine like cgocallbackg is going to return to that 790 // PC (because the frame we allocate below has the same 791 // size as cgocallback_gofunc's frame declared above) 792 // so that the traceback will seamlessly trace back into 793 // the earlier calls. 794 // 795 // In the new goroutine, 4(SP) holds the saved oldm (DX) register. 796 // 8(SP) is unused. 797 MOVL m_curg(BP), SI 798 MOVL SI, g(CX) 799 MOVL (g_sched+gobuf_sp)(SI), DI // prepare stack as DI 800 MOVL (g_sched+gobuf_pc)(SI), BP 801 MOVL BP, -4(DI) 802 MOVL ctxt+12(FP), CX 803 LEAL -(4+12)(DI), SP 804 MOVL DX, 4(SP) 805 MOVL CX, 0(SP) 806 CALL runtime·cgocallbackg(SB) 807 MOVL 4(SP), DX 808 809 // Restore g->sched (== m->curg->sched) from saved values. 810 get_tls(CX) 811 MOVL g(CX), SI 812 MOVL 12(SP), BP 813 MOVL BP, (g_sched+gobuf_pc)(SI) 814 LEAL (12+4)(SP), DI 815 MOVL DI, (g_sched+gobuf_sp)(SI) 816 817 // Switch back to m->g0's stack and restore m->g0->sched.sp. 818 // (Unlike m->curg, the g0 goroutine never uses sched.pc, 819 // so we do not have to restore it.) 820 MOVL g(CX), BP 821 MOVL g_m(BP), BP 822 MOVL m_g0(BP), SI 823 MOVL SI, g(CX) 824 MOVL (g_sched+gobuf_sp)(SI), SP 825 MOVL 0(SP), AX 826 MOVL AX, (g_sched+gobuf_sp)(SI) 827 828 // If the m on entry was nil, we called needm above to borrow an m 829 // for the duration of the call. Since the call is over, return it with dropm. 830 CMPL DX, $0 831 JNE 3(PC) 832 MOVL $runtime·dropm(SB), AX 833 CALL AX 834 835 // Done! 836 RET 837 838 // void setg(G*); set g. for use by needm. 839 TEXT runtime·setg(SB), NOSPLIT, $0-4 840 MOVL gg+0(FP), BX 841 #ifdef GOOS_windows 842 CMPL BX, $0 843 JNE settls 844 MOVL $0, 0x14(FS) 845 RET 846 settls: 847 MOVL g_m(BX), AX 848 LEAL m_tls(AX), AX 849 MOVL AX, 0x14(FS) 850 #endif 851 get_tls(CX) 852 MOVL BX, g(CX) 853 RET 854 855 // void setg_gcc(G*); set g. for use by gcc 856 TEXT setg_gcc<>(SB), NOSPLIT, $0 857 get_tls(AX) 858 MOVL gg+0(FP), DX 859 MOVL DX, g(AX) 860 RET 861 862 TEXT runtime·abort(SB),NOSPLIT,$0-0 863 INT $3 864 loop: 865 JMP loop 866 867 // check that SP is in range [g->stack.lo, g->stack.hi) 868 TEXT runtime·stackcheck(SB), NOSPLIT, $0-0 869 get_tls(CX) 870 MOVL g(CX), AX 871 CMPL (g_stack+stack_hi)(AX), SP 872 JHI 2(PC) 873 CALL runtime·abort(SB) 874 CMPL SP, (g_stack+stack_lo)(AX) 875 JHI 2(PC) 876 CALL runtime·abort(SB) 877 RET 878 879 // func cputicks() int64 880 TEXT runtime·cputicks(SB),NOSPLIT,$0-8 881 CMPB internal∕cpu·X86+const_offsetX86HasSSE2(SB), $1 882 JNE done 883 CMPB runtime·lfenceBeforeRdtsc(SB), $1 884 JNE mfence 885 LFENCE 886 JMP done 887 mfence: 888 MFENCE 889 done: 890 RDTSC 891 MOVL AX, ret_lo+0(FP) 892 MOVL DX, ret_hi+4(FP) 893 RET 894 895 TEXT runtime·ldt0setup(SB),NOSPLIT,$16-0 896 // set up ldt 7 to point at m0.tls 897 // ldt 1 would be fine on Linux, but on OS X, 7 is as low as we can go. 898 // the entry number is just a hint. setldt will set up GS with what it used. 899 MOVL $7, 0(SP) 900 LEAL runtime·m0+m_tls(SB), AX 901 MOVL AX, 4(SP) 902 MOVL $32, 8(SP) // sizeof(tls array) 903 CALL runtime·setldt(SB) 904 RET 905 906 TEXT runtime·emptyfunc(SB),0,$0-0 907 RET 908 909 // hash function using AES hardware instructions 910 TEXT runtime·aeshash(SB),NOSPLIT,$0-16 911 MOVL p+0(FP), AX // ptr to data 912 MOVL s+8(FP), BX // size 913 LEAL ret+12(FP), DX 914 JMP runtime·aeshashbody(SB) 915 916 TEXT runtime·aeshashstr(SB),NOSPLIT,$0-12 917 MOVL p+0(FP), AX // ptr to string object 918 MOVL 4(AX), BX // length of string 919 MOVL (AX), AX // string data 920 LEAL ret+8(FP), DX 921 JMP runtime·aeshashbody(SB) 922 923 // AX: data 924 // BX: length 925 // DX: address to put return value 926 TEXT runtime·aeshashbody(SB),NOSPLIT,$0-0 927 MOVL h+4(FP), X0 // 32 bits of per-table hash seed 928 PINSRW $4, BX, X0 // 16 bits of length 929 PSHUFHW $0, X0, X0 // replace size with its low 2 bytes repeated 4 times 930 MOVO X0, X1 // save unscrambled seed 931 PXOR runtime·aeskeysched(SB), X0 // xor in per-process seed 932 AESENC X0, X0 // scramble seed 933 934 CMPL BX, $16 935 JB aes0to15 936 JE aes16 937 CMPL BX, $32 938 JBE aes17to32 939 CMPL BX, $64 940 JBE aes33to64 941 JMP aes65plus 942 943 aes0to15: 944 TESTL BX, BX 945 JE aes0 946 947 ADDL $16, AX 948 TESTW $0xff0, AX 949 JE endofpage 950 951 // 16 bytes loaded at this address won't cross 952 // a page boundary, so we can load it directly. 953 MOVOU -16(AX), X1 954 ADDL BX, BX 955 PAND masks<>(SB)(BX*8), X1 956 957 final1: 958 AESENC X0, X1 // scramble input, xor in seed 959 AESENC X1, X1 // scramble combo 2 times 960 AESENC X1, X1 961 MOVL X1, (DX) 962 RET 963 964 endofpage: 965 // address ends in 1111xxxx. Might be up against 966 // a page boundary, so load ending at last byte. 967 // Then shift bytes down using pshufb. 968 MOVOU -32(AX)(BX*1), X1 969 ADDL BX, BX 970 PSHUFB shifts<>(SB)(BX*8), X1 971 JMP final1 972 973 aes0: 974 // Return scrambled input seed 975 AESENC X0, X0 976 MOVL X0, (DX) 977 RET 978 979 aes16: 980 MOVOU (AX), X1 981 JMP final1 982 983 aes17to32: 984 // make second starting seed 985 PXOR runtime·aeskeysched+16(SB), X1 986 AESENC X1, X1 987 988 // load data to be hashed 989 MOVOU (AX), X2 990 MOVOU -16(AX)(BX*1), X3 991 992 // scramble 3 times 993 AESENC X0, X2 994 AESENC X1, X3 995 AESENC X2, X2 996 AESENC X3, X3 997 AESENC X2, X2 998 AESENC X3, X3 999 1000 // combine results 1001 PXOR X3, X2 1002 MOVL X2, (DX) 1003 RET 1004 1005 aes33to64: 1006 // make 3 more starting seeds 1007 MOVO X1, X2 1008 MOVO X1, X3 1009 PXOR runtime·aeskeysched+16(SB), X1 1010 PXOR runtime·aeskeysched+32(SB), X2 1011 PXOR runtime·aeskeysched+48(SB), X3 1012 AESENC X1, X1 1013 AESENC X2, X2 1014 AESENC X3, X3 1015 1016 MOVOU (AX), X4 1017 MOVOU 16(AX), X5 1018 MOVOU -32(AX)(BX*1), X6 1019 MOVOU -16(AX)(BX*1), X7 1020 1021 AESENC X0, X4 1022 AESENC X1, X5 1023 AESENC X2, X6 1024 AESENC X3, X7 1025 1026 AESENC X4, X4 1027 AESENC X5, X5 1028 AESENC X6, X6 1029 AESENC X7, X7 1030 1031 AESENC X4, X4 1032 AESENC X5, X5 1033 AESENC X6, X6 1034 AESENC X7, X7 1035 1036 PXOR X6, X4 1037 PXOR X7, X5 1038 PXOR X5, X4 1039 MOVL X4, (DX) 1040 RET 1041 1042 aes65plus: 1043 // make 3 more starting seeds 1044 MOVO X1, X2 1045 MOVO X1, X3 1046 PXOR runtime·aeskeysched+16(SB), X1 1047 PXOR runtime·aeskeysched+32(SB), X2 1048 PXOR runtime·aeskeysched+48(SB), X3 1049 AESENC X1, X1 1050 AESENC X2, X2 1051 AESENC X3, X3 1052 1053 // start with last (possibly overlapping) block 1054 MOVOU -64(AX)(BX*1), X4 1055 MOVOU -48(AX)(BX*1), X5 1056 MOVOU -32(AX)(BX*1), X6 1057 MOVOU -16(AX)(BX*1), X7 1058 1059 // scramble state once 1060 AESENC X0, X4 1061 AESENC X1, X5 1062 AESENC X2, X6 1063 AESENC X3, X7 1064 1065 // compute number of remaining 64-byte blocks 1066 DECL BX 1067 SHRL $6, BX 1068 1069 aesloop: 1070 // scramble state, xor in a block 1071 MOVOU (AX), X0 1072 MOVOU 16(AX), X1 1073 MOVOU 32(AX), X2 1074 MOVOU 48(AX), X3 1075 AESENC X0, X4 1076 AESENC X1, X5 1077 AESENC X2, X6 1078 AESENC X3, X7 1079 1080 // scramble state 1081 AESENC X4, X4 1082 AESENC X5, X5 1083 AESENC X6, X6 1084 AESENC X7, X7 1085 1086 ADDL $64, AX 1087 DECL BX 1088 JNE aesloop 1089 1090 // 2 more scrambles to finish 1091 AESENC X4, X4 1092 AESENC X5, X5 1093 AESENC X6, X6 1094 AESENC X7, X7 1095 1096 AESENC X4, X4 1097 AESENC X5, X5 1098 AESENC X6, X6 1099 AESENC X7, X7 1100 1101 PXOR X6, X4 1102 PXOR X7, X5 1103 PXOR X5, X4 1104 MOVL X4, (DX) 1105 RET 1106 1107 TEXT runtime·aeshash32(SB),NOSPLIT,$0-12 1108 MOVL p+0(FP), AX // ptr to data 1109 MOVL h+4(FP), X0 // seed 1110 PINSRD $1, (AX), X0 // data 1111 AESENC runtime·aeskeysched+0(SB), X0 1112 AESENC runtime·aeskeysched+16(SB), X0 1113 AESENC runtime·aeskeysched+32(SB), X0 1114 MOVL X0, ret+8(FP) 1115 RET 1116 1117 TEXT runtime·aeshash64(SB),NOSPLIT,$0-12 1118 MOVL p+0(FP), AX // ptr to data 1119 MOVQ (AX), X0 // data 1120 PINSRD $2, h+4(FP), X0 // seed 1121 AESENC runtime·aeskeysched+0(SB), X0 1122 AESENC runtime·aeskeysched+16(SB), X0 1123 AESENC runtime·aeskeysched+32(SB), X0 1124 MOVL X0, ret+8(FP) 1125 RET 1126 1127 // simple mask to get rid of data in the high part of the register. 1128 DATA masks<>+0x00(SB)/4, $0x00000000 1129 DATA masks<>+0x04(SB)/4, $0x00000000 1130 DATA masks<>+0x08(SB)/4, $0x00000000 1131 DATA masks<>+0x0c(SB)/4, $0x00000000 1132 1133 DATA masks<>+0x10(SB)/4, $0x000000ff 1134 DATA masks<>+0x14(SB)/4, $0x00000000 1135 DATA masks<>+0x18(SB)/4, $0x00000000 1136 DATA masks<>+0x1c(SB)/4, $0x00000000 1137 1138 DATA masks<>+0x20(SB)/4, $0x0000ffff 1139 DATA masks<>+0x24(SB)/4, $0x00000000 1140 DATA masks<>+0x28(SB)/4, $0x00000000 1141 DATA masks<>+0x2c(SB)/4, $0x00000000 1142 1143 DATA masks<>+0x30(SB)/4, $0x00ffffff 1144 DATA masks<>+0x34(SB)/4, $0x00000000 1145 DATA masks<>+0x38(SB)/4, $0x00000000 1146 DATA masks<>+0x3c(SB)/4, $0x00000000 1147 1148 DATA masks<>+0x40(SB)/4, $0xffffffff 1149 DATA masks<>+0x44(SB)/4, $0x00000000 1150 DATA masks<>+0x48(SB)/4, $0x00000000 1151 DATA masks<>+0x4c(SB)/4, $0x00000000 1152 1153 DATA masks<>+0x50(SB)/4, $0xffffffff 1154 DATA masks<>+0x54(SB)/4, $0x000000ff 1155 DATA masks<>+0x58(SB)/4, $0x00000000 1156 DATA masks<>+0x5c(SB)/4, $0x00000000 1157 1158 DATA masks<>+0x60(SB)/4, $0xffffffff 1159 DATA masks<>+0x64(SB)/4, $0x0000ffff 1160 DATA masks<>+0x68(SB)/4, $0x00000000 1161 DATA masks<>+0x6c(SB)/4, $0x00000000 1162 1163 DATA masks<>+0x70(SB)/4, $0xffffffff 1164 DATA masks<>+0x74(SB)/4, $0x00ffffff 1165 DATA masks<>+0x78(SB)/4, $0x00000000 1166 DATA masks<>+0x7c(SB)/4, $0x00000000 1167 1168 DATA masks<>+0x80(SB)/4, $0xffffffff 1169 DATA masks<>+0x84(SB)/4, $0xffffffff 1170 DATA masks<>+0x88(SB)/4, $0x00000000 1171 DATA masks<>+0x8c(SB)/4, $0x00000000 1172 1173 DATA masks<>+0x90(SB)/4, $0xffffffff 1174 DATA masks<>+0x94(SB)/4, $0xffffffff 1175 DATA masks<>+0x98(SB)/4, $0x000000ff 1176 DATA masks<>+0x9c(SB)/4, $0x00000000 1177 1178 DATA masks<>+0xa0(SB)/4, $0xffffffff 1179 DATA masks<>+0xa4(SB)/4, $0xffffffff 1180 DATA masks<>+0xa8(SB)/4, $0x0000ffff 1181 DATA masks<>+0xac(SB)/4, $0x00000000 1182 1183 DATA masks<>+0xb0(SB)/4, $0xffffffff 1184 DATA masks<>+0xb4(SB)/4, $0xffffffff 1185 DATA masks<>+0xb8(SB)/4, $0x00ffffff 1186 DATA masks<>+0xbc(SB)/4, $0x00000000 1187 1188 DATA masks<>+0xc0(SB)/4, $0xffffffff 1189 DATA masks<>+0xc4(SB)/4, $0xffffffff 1190 DATA masks<>+0xc8(SB)/4, $0xffffffff 1191 DATA masks<>+0xcc(SB)/4, $0x00000000 1192 1193 DATA masks<>+0xd0(SB)/4, $0xffffffff 1194 DATA masks<>+0xd4(SB)/4, $0xffffffff 1195 DATA masks<>+0xd8(SB)/4, $0xffffffff 1196 DATA masks<>+0xdc(SB)/4, $0x000000ff 1197 1198 DATA masks<>+0xe0(SB)/4, $0xffffffff 1199 DATA masks<>+0xe4(SB)/4, $0xffffffff 1200 DATA masks<>+0xe8(SB)/4, $0xffffffff 1201 DATA masks<>+0xec(SB)/4, $0x0000ffff 1202 1203 DATA masks<>+0xf0(SB)/4, $0xffffffff 1204 DATA masks<>+0xf4(SB)/4, $0xffffffff 1205 DATA masks<>+0xf8(SB)/4, $0xffffffff 1206 DATA masks<>+0xfc(SB)/4, $0x00ffffff 1207 1208 GLOBL masks<>(SB),RODATA,$256 1209 1210 // these are arguments to pshufb. They move data down from 1211 // the high bytes of the register to the low bytes of the register. 1212 // index is how many bytes to move. 1213 DATA shifts<>+0x00(SB)/4, $0x00000000 1214 DATA shifts<>+0x04(SB)/4, $0x00000000 1215 DATA shifts<>+0x08(SB)/4, $0x00000000 1216 DATA shifts<>+0x0c(SB)/4, $0x00000000 1217 1218 DATA shifts<>+0x10(SB)/4, $0xffffff0f 1219 DATA shifts<>+0x14(SB)/4, $0xffffffff 1220 DATA shifts<>+0x18(SB)/4, $0xffffffff 1221 DATA shifts<>+0x1c(SB)/4, $0xffffffff 1222 1223 DATA shifts<>+0x20(SB)/4, $0xffff0f0e 1224 DATA shifts<>+0x24(SB)/4, $0xffffffff 1225 DATA shifts<>+0x28(SB)/4, $0xffffffff 1226 DATA shifts<>+0x2c(SB)/4, $0xffffffff 1227 1228 DATA shifts<>+0x30(SB)/4, $0xff0f0e0d 1229 DATA shifts<>+0x34(SB)/4, $0xffffffff 1230 DATA shifts<>+0x38(SB)/4, $0xffffffff 1231 DATA shifts<>+0x3c(SB)/4, $0xffffffff 1232 1233 DATA shifts<>+0x40(SB)/4, $0x0f0e0d0c 1234 DATA shifts<>+0x44(SB)/4, $0xffffffff 1235 DATA shifts<>+0x48(SB)/4, $0xffffffff 1236 DATA shifts<>+0x4c(SB)/4, $0xffffffff 1237 1238 DATA shifts<>+0x50(SB)/4, $0x0e0d0c0b 1239 DATA shifts<>+0x54(SB)/4, $0xffffff0f 1240 DATA shifts<>+0x58(SB)/4, $0xffffffff 1241 DATA shifts<>+0x5c(SB)/4, $0xffffffff 1242 1243 DATA shifts<>+0x60(SB)/4, $0x0d0c0b0a 1244 DATA shifts<>+0x64(SB)/4, $0xffff0f0e 1245 DATA shifts<>+0x68(SB)/4, $0xffffffff 1246 DATA shifts<>+0x6c(SB)/4, $0xffffffff 1247 1248 DATA shifts<>+0x70(SB)/4, $0x0c0b0a09 1249 DATA shifts<>+0x74(SB)/4, $0xff0f0e0d 1250 DATA shifts<>+0x78(SB)/4, $0xffffffff 1251 DATA shifts<>+0x7c(SB)/4, $0xffffffff 1252 1253 DATA shifts<>+0x80(SB)/4, $0x0b0a0908 1254 DATA shifts<>+0x84(SB)/4, $0x0f0e0d0c 1255 DATA shifts<>+0x88(SB)/4, $0xffffffff 1256 DATA shifts<>+0x8c(SB)/4, $0xffffffff 1257 1258 DATA shifts<>+0x90(SB)/4, $0x0a090807 1259 DATA shifts<>+0x94(SB)/4, $0x0e0d0c0b 1260 DATA shifts<>+0x98(SB)/4, $0xffffff0f 1261 DATA shifts<>+0x9c(SB)/4, $0xffffffff 1262 1263 DATA shifts<>+0xa0(SB)/4, $0x09080706 1264 DATA shifts<>+0xa4(SB)/4, $0x0d0c0b0a 1265 DATA shifts<>+0xa8(SB)/4, $0xffff0f0e 1266 DATA shifts<>+0xac(SB)/4, $0xffffffff 1267 1268 DATA shifts<>+0xb0(SB)/4, $0x08070605 1269 DATA shifts<>+0xb4(SB)/4, $0x0c0b0a09 1270 DATA shifts<>+0xb8(SB)/4, $0xff0f0e0d 1271 DATA shifts<>+0xbc(SB)/4, $0xffffffff 1272 1273 DATA shifts<>+0xc0(SB)/4, $0x07060504 1274 DATA shifts<>+0xc4(SB)/4, $0x0b0a0908 1275 DATA shifts<>+0xc8(SB)/4, $0x0f0e0d0c 1276 DATA shifts<>+0xcc(SB)/4, $0xffffffff 1277 1278 DATA shifts<>+0xd0(SB)/4, $0x06050403 1279 DATA shifts<>+0xd4(SB)/4, $0x0a090807 1280 DATA shifts<>+0xd8(SB)/4, $0x0e0d0c0b 1281 DATA shifts<>+0xdc(SB)/4, $0xffffff0f 1282 1283 DATA shifts<>+0xe0(SB)/4, $0x05040302 1284 DATA shifts<>+0xe4(SB)/4, $0x09080706 1285 DATA shifts<>+0xe8(SB)/4, $0x0d0c0b0a 1286 DATA shifts<>+0xec(SB)/4, $0xffff0f0e 1287 1288 DATA shifts<>+0xf0(SB)/4, $0x04030201 1289 DATA shifts<>+0xf4(SB)/4, $0x08070605 1290 DATA shifts<>+0xf8(SB)/4, $0x0c0b0a09 1291 DATA shifts<>+0xfc(SB)/4, $0xff0f0e0d 1292 1293 GLOBL shifts<>(SB),RODATA,$256 1294 1295 TEXT ·checkASM(SB),NOSPLIT,$0-1 1296 // check that masks<>(SB) and shifts<>(SB) are aligned to 16-byte 1297 MOVL $masks<>(SB), AX 1298 MOVL $shifts<>(SB), BX 1299 ORL BX, AX 1300 TESTL $15, AX 1301 SETEQ ret+0(FP) 1302 RET 1303 1304 TEXT runtime·return0(SB), NOSPLIT, $0 1305 MOVL $0, AX 1306 RET 1307 1308 // Called from cgo wrappers, this function returns g->m->curg.stack.hi. 1309 // Must obey the gcc calling convention. 1310 TEXT _cgo_topofstack(SB),NOSPLIT,$0 1311 get_tls(CX) 1312 MOVL g(CX), AX 1313 MOVL g_m(AX), AX 1314 MOVL m_curg(AX), AX 1315 MOVL (g_stack+stack_hi)(AX), AX 1316 RET 1317 1318 // The top-most function running on a goroutine 1319 // returns to goexit+PCQuantum. 1320 TEXT runtime·goexit(SB),NOSPLIT,$0-0 1321 BYTE $0x90 // NOP 1322 CALL runtime·goexit1(SB) // does not return 1323 // traceback from goexit1 must hit code range of goexit 1324 BYTE $0x90 // NOP 1325 1326 // Add a module's moduledata to the linked list of moduledata objects. This 1327 // is called from .init_array by a function generated in the linker and so 1328 // follows the platform ABI wrt register preservation -- it only touches AX, 1329 // CX (implicitly) and DX, but it does not follow the ABI wrt arguments: 1330 // instead the pointer to the moduledata is passed in AX. 1331 TEXT runtime·addmoduledata(SB),NOSPLIT,$0-0 1332 MOVL runtime·lastmoduledatap(SB), DX 1333 MOVL AX, moduledata_next(DX) 1334 MOVL AX, runtime·lastmoduledatap(SB) 1335 RET 1336 1337 TEXT runtime·uint32tofloat64(SB),NOSPLIT,$8-12 1338 MOVL a+0(FP), AX 1339 MOVL AX, 0(SP) 1340 MOVL $0, 4(SP) 1341 FMOVV 0(SP), F0 1342 FMOVDP F0, ret+4(FP) 1343 RET 1344 1345 TEXT runtime·float64touint32(SB),NOSPLIT,$12-12 1346 FMOVD a+0(FP), F0 1347 FSTCW 0(SP) 1348 FLDCW runtime·controlWord64trunc(SB) 1349 FMOVVP F0, 4(SP) 1350 FLDCW 0(SP) 1351 MOVL 4(SP), AX 1352 MOVL AX, ret+8(FP) 1353 RET 1354 1355 // gcWriteBarrier performs a heap pointer write and informs the GC. 1356 // 1357 // gcWriteBarrier does NOT follow the Go ABI. It takes two arguments: 1358 // - DI is the destination of the write 1359 // - AX is the value being written at DI 1360 // It clobbers FLAGS. It does not clobber any general-purpose registers, 1361 // but may clobber others (e.g., SSE registers). 1362 TEXT runtime·gcWriteBarrier(SB),NOSPLIT,$28 1363 // Save the registers clobbered by the fast path. This is slightly 1364 // faster than having the caller spill these. 1365 MOVL CX, 20(SP) 1366 MOVL BX, 24(SP) 1367 // TODO: Consider passing g.m.p in as an argument so they can be shared 1368 // across a sequence of write barriers. 1369 get_tls(BX) 1370 MOVL g(BX), BX 1371 MOVL g_m(BX), BX 1372 MOVL m_p(BX), BX 1373 MOVL (p_wbBuf+wbBuf_next)(BX), CX 1374 // Increment wbBuf.next position. 1375 LEAL 8(CX), CX 1376 MOVL CX, (p_wbBuf+wbBuf_next)(BX) 1377 CMPL CX, (p_wbBuf+wbBuf_end)(BX) 1378 // Record the write. 1379 MOVL AX, -8(CX) // Record value 1380 MOVL (DI), BX // TODO: This turns bad writes into bad reads. 1381 MOVL BX, -4(CX) // Record *slot 1382 // Is the buffer full? (flags set in CMPL above) 1383 JEQ flush 1384 ret: 1385 MOVL 20(SP), CX 1386 MOVL 24(SP), BX 1387 // Do the write. 1388 MOVL AX, (DI) 1389 RET 1390 1391 flush: 1392 // Save all general purpose registers since these could be 1393 // clobbered by wbBufFlush and were not saved by the caller. 1394 MOVL DI, 0(SP) // Also first argument to wbBufFlush 1395 MOVL AX, 4(SP) // Also second argument to wbBufFlush 1396 // BX already saved 1397 // CX already saved 1398 MOVL DX, 8(SP) 1399 MOVL BP, 12(SP) 1400 MOVL SI, 16(SP) 1401 // DI already saved 1402 1403 // This takes arguments DI and AX 1404 CALL runtime·wbBufFlush(SB) 1405 1406 MOVL 0(SP), DI 1407 MOVL 4(SP), AX 1408 MOVL 8(SP), DX 1409 MOVL 12(SP), BP 1410 MOVL 16(SP), SI 1411 JMP ret