github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/runtime/sys_linux_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 // 6 // System calls and other sys.stuff for 386, Linux 7 // 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // Most linux systems use glibc's dynamic linker, which puts the 14 // __kernel_vsyscall vdso helper at 0x10(GS) for easy access from position 15 // independent code and setldt in runtime does the same in the statically 16 // linked case. However, systems that use alternative libc such as Android's 17 // bionic and musl, do not save the helper anywhere, and so the only way to 18 // invoke a syscall from position independent code is boring old int $0x80 19 // (which is also what syscall wrappers in bionic/musl use). 20 // 21 // The benchmarks also showed that using int $0x80 is as fast as calling 22 // *%gs:0x10 except on AMD Opteron. See https://golang.org/cl/19833 23 // for the benchmark program and raw data. 24 //#define INVOKE_SYSCALL CALL 0x10(GS) // non-portable 25 #define INVOKE_SYSCALL INT $0x80 26 27 #define SYS_exit 1 28 #define SYS_read 3 29 #define SYS_write 4 30 #define SYS_open 5 31 #define SYS_close 6 32 #define SYS_getpid 20 33 #define SYS_access 33 34 #define SYS_kill 37 35 #define SYS_brk 45 36 #define SYS_fcntl 55 37 #define SYS_munmap 91 38 #define SYS_socketcall 102 39 #define SYS_setittimer 104 40 #define SYS_clone 120 41 #define SYS_sched_yield 158 42 #define SYS_rt_sigreturn 173 43 #define SYS_rt_sigaction 174 44 #define SYS_rt_sigprocmask 175 45 #define SYS_sigaltstack 186 46 #define SYS_ugetrlimit 191 47 #define SYS_mmap2 192 48 #define SYS_mincore 218 49 #define SYS_madvise 219 50 #define SYS_gettid 224 51 #define SYS_tkill 238 52 #define SYS_futex 240 53 #define SYS_sched_getaffinity 242 54 #define SYS_set_thread_area 243 55 #define SYS_exit_group 252 56 #define SYS_epoll_create 254 57 #define SYS_epoll_ctl 255 58 #define SYS_epoll_wait 256 59 #define SYS_clock_gettime 265 60 #define SYS_pselect6 308 61 #define SYS_epoll_create1 329 62 63 TEXT runtime·exit(SB),NOSPLIT,$0 64 MOVL $SYS_exit_group, AX 65 MOVL code+0(FP), BX 66 INVOKE_SYSCALL 67 INT $3 // not reached 68 RET 69 70 TEXT exit1<>(SB),NOSPLIT,$0 71 MOVL $SYS_exit, AX 72 MOVL code+0(FP), BX 73 INVOKE_SYSCALL 74 INT $3 // not reached 75 RET 76 77 // func exitThread(wait *uint32) 78 TEXT runtime·exitThread(SB),NOSPLIT,$0-4 79 MOVL wait+0(FP), AX 80 // We're done using the stack. 81 MOVL $0, (AX) 82 MOVL $1, AX // exit (just this thread) 83 MOVL $0, BX // exit code 84 INT $0x80 // no stack; must not use CALL 85 // We may not even have a stack any more. 86 INT $3 87 JMP 0(PC) 88 89 TEXT runtime·open(SB),NOSPLIT,$0 90 MOVL $SYS_open, AX 91 MOVL name+0(FP), BX 92 MOVL mode+4(FP), CX 93 MOVL perm+8(FP), DX 94 INVOKE_SYSCALL 95 CMPL AX, $0xfffff001 96 JLS 2(PC) 97 MOVL $-1, AX 98 MOVL AX, ret+12(FP) 99 RET 100 101 TEXT runtime·closefd(SB),NOSPLIT,$0 102 MOVL $SYS_close, AX 103 MOVL fd+0(FP), BX 104 INVOKE_SYSCALL 105 CMPL AX, $0xfffff001 106 JLS 2(PC) 107 MOVL $-1, AX 108 MOVL AX, ret+4(FP) 109 RET 110 111 TEXT runtime·write(SB),NOSPLIT,$0 112 MOVL $SYS_write, AX 113 MOVL fd+0(FP), BX 114 MOVL p+4(FP), CX 115 MOVL n+8(FP), DX 116 INVOKE_SYSCALL 117 CMPL AX, $0xfffff001 118 JLS 2(PC) 119 MOVL $-1, AX 120 MOVL AX, ret+12(FP) 121 RET 122 123 TEXT runtime·read(SB),NOSPLIT,$0 124 MOVL $SYS_read, AX 125 MOVL fd+0(FP), BX 126 MOVL p+4(FP), CX 127 MOVL n+8(FP), DX 128 INVOKE_SYSCALL 129 CMPL AX, $0xfffff001 130 JLS 2(PC) 131 MOVL $-1, AX 132 MOVL AX, ret+12(FP) 133 RET 134 135 TEXT runtime·getrlimit(SB),NOSPLIT,$0 136 MOVL $SYS_ugetrlimit, AX 137 MOVL kind+0(FP), BX 138 MOVL limit+4(FP), CX 139 INVOKE_SYSCALL 140 MOVL AX, ret+8(FP) 141 RET 142 143 TEXT runtime·usleep(SB),NOSPLIT,$8 144 MOVL $0, DX 145 MOVL usec+0(FP), AX 146 MOVL $1000000, CX 147 DIVL CX 148 MOVL AX, 0(SP) 149 MOVL $1000, AX // usec to nsec 150 MULL DX 151 MOVL AX, 4(SP) 152 153 // pselect6(0, 0, 0, 0, &ts, 0) 154 MOVL $SYS_pselect6, AX 155 MOVL $0, BX 156 MOVL $0, CX 157 MOVL $0, DX 158 MOVL $0, SI 159 LEAL 0(SP), DI 160 MOVL $0, BP 161 INVOKE_SYSCALL 162 RET 163 164 TEXT runtime·gettid(SB),NOSPLIT,$0-4 165 MOVL $SYS_gettid, AX 166 INVOKE_SYSCALL 167 MOVL AX, ret+0(FP) 168 RET 169 170 TEXT runtime·raise(SB),NOSPLIT,$12 171 MOVL $SYS_gettid, AX 172 INVOKE_SYSCALL 173 MOVL AX, BX // arg 1 tid 174 MOVL sig+0(FP), CX // arg 2 signal 175 MOVL $SYS_tkill, AX 176 INVOKE_SYSCALL 177 RET 178 179 TEXT runtime·raiseproc(SB),NOSPLIT,$12 180 MOVL $SYS_getpid, AX 181 INVOKE_SYSCALL 182 MOVL AX, BX // arg 1 pid 183 MOVL sig+0(FP), CX // arg 2 signal 184 MOVL $SYS_kill, AX 185 INVOKE_SYSCALL 186 RET 187 188 TEXT runtime·setitimer(SB),NOSPLIT,$0-12 189 MOVL $SYS_setittimer, AX 190 MOVL mode+0(FP), BX 191 MOVL new+4(FP), CX 192 MOVL old+8(FP), DX 193 INVOKE_SYSCALL 194 RET 195 196 TEXT runtime·mincore(SB),NOSPLIT,$0-16 197 MOVL $SYS_mincore, AX 198 MOVL addr+0(FP), BX 199 MOVL n+4(FP), CX 200 MOVL dst+8(FP), DX 201 INVOKE_SYSCALL 202 MOVL AX, ret+12(FP) 203 RET 204 205 // func walltime() (sec int64, nsec int32) 206 TEXT runtime·walltime(SB), NOSPLIT, $16 207 // Stack layout, depending on call path: 208 // x(SP) vDSO INVOKE_SYSCALL 209 // 12 ts.tv_nsec ts.tv_nsec 210 // 8 ts.tv_sec ts.tv_sec 211 // 4 &ts - 212 // 0 CLOCK_<id> - 213 // 214 // If we take the vDSO path, we're calling a function with gcc calling convention. 215 // We're guaranteed 128 bytes on entry. We've taken 16, and the call uses another 4, 216 // leaving 108 for __vdso_clock_gettime to use. 217 MOVL runtime·__vdso_clock_gettime_sym(SB), AX 218 CMPL AX, $0 219 JEQ fallback 220 221 LEAL 8(SP), BX // &ts (struct timespec) 222 MOVL BX, 4(SP) 223 MOVL $0, 0(SP) // CLOCK_REALTIME 224 CALL AX 225 JMP finish 226 227 fallback: 228 MOVL $SYS_clock_gettime, AX 229 MOVL $0, BX // CLOCK_REALTIME 230 LEAL 8(SP), CX 231 INVOKE_SYSCALL 232 233 finish: 234 MOVL 8(SP), AX // sec 235 MOVL 12(SP), BX // nsec 236 237 // sec is in AX, nsec in BX 238 MOVL AX, sec_lo+0(FP) 239 MOVL $0, sec_hi+4(FP) 240 MOVL BX, nsec+8(FP) 241 RET 242 243 // int64 nanotime(void) so really 244 // void nanotime(int64 *nsec) 245 TEXT runtime·nanotime(SB), NOSPLIT, $16 246 // See comments above in walltime() about stack space usage and layout. 247 MOVL runtime·__vdso_clock_gettime_sym(SB), AX 248 CMPL AX, $0 249 JEQ fallback 250 251 LEAL 8(SP), BX // &ts (struct timespec) 252 MOVL BX, 4(SP) 253 MOVL $1, 0(SP) // CLOCK_MONOTONIC 254 CALL AX 255 JMP finish 256 257 fallback: 258 MOVL $SYS_clock_gettime, AX 259 MOVL $1, BX // CLOCK_MONOTONIC 260 LEAL 8(SP), CX 261 INVOKE_SYSCALL 262 263 finish: 264 MOVL 8(SP), AX // sec 265 MOVL 12(SP), BX // nsec 266 267 // sec is in AX, nsec in BX 268 // convert to DX:AX nsec 269 MOVL $1000000000, CX 270 MULL CX 271 ADDL BX, AX 272 ADCL $0, DX 273 274 MOVL AX, ret_lo+0(FP) 275 MOVL DX, ret_hi+4(FP) 276 RET 277 278 TEXT runtime·rtsigprocmask(SB),NOSPLIT,$0 279 MOVL $SYS_rt_sigprocmask, AX 280 MOVL how+0(FP), BX 281 MOVL new+4(FP), CX 282 MOVL old+8(FP), DX 283 MOVL size+12(FP), SI 284 INVOKE_SYSCALL 285 CMPL AX, $0xfffff001 286 JLS 2(PC) 287 INT $3 288 RET 289 290 TEXT runtime·rt_sigaction(SB),NOSPLIT,$0 291 MOVL $SYS_rt_sigaction, AX 292 MOVL sig+0(FP), BX 293 MOVL new+4(FP), CX 294 MOVL old+8(FP), DX 295 MOVL size+12(FP), SI 296 INVOKE_SYSCALL 297 MOVL AX, ret+16(FP) 298 RET 299 300 TEXT runtime·sigfwd(SB),NOSPLIT,$12-16 301 MOVL fn+0(FP), AX 302 MOVL sig+4(FP), BX 303 MOVL info+8(FP), CX 304 MOVL ctx+12(FP), DX 305 MOVL SP, SI 306 SUBL $32, SP 307 ANDL $-15, SP // align stack: handler might be a C function 308 MOVL BX, 0(SP) 309 MOVL CX, 4(SP) 310 MOVL DX, 8(SP) 311 MOVL SI, 12(SP) // save SI: handler might be a Go function 312 CALL AX 313 MOVL 12(SP), AX 314 MOVL AX, SP 315 RET 316 317 TEXT runtime·sigtramp(SB),NOSPLIT,$28 318 // Save callee-saved C registers, since the caller may be a C signal handler. 319 MOVL BX, bx-4(SP) 320 MOVL BP, bp-8(SP) 321 MOVL SI, si-12(SP) 322 MOVL DI, di-16(SP) 323 // We don't save mxcsr or the x87 control word because sigtrampgo doesn't 324 // modify them. 325 326 MOVL sig+0(FP), BX 327 MOVL BX, 0(SP) 328 MOVL info+4(FP), BX 329 MOVL BX, 4(SP) 330 MOVL ctx+8(FP), BX 331 MOVL BX, 8(SP) 332 CALL runtime·sigtrampgo(SB) 333 334 MOVL di-16(SP), DI 335 MOVL si-12(SP), SI 336 MOVL bp-8(SP), BP 337 MOVL bx-4(SP), BX 338 RET 339 340 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0 341 JMP runtime·sigtramp(SB) 342 343 TEXT runtime·sigreturn(SB),NOSPLIT,$0 344 MOVL $SYS_rt_sigreturn, AX 345 // Sigreturn expects same SP as signal handler, 346 // so cannot CALL 0x10(GS) here. 347 INT $0x80 348 INT $3 // not reached 349 RET 350 351 TEXT runtime·mmap(SB),NOSPLIT,$0 352 MOVL $SYS_mmap2, AX 353 MOVL addr+0(FP), BX 354 MOVL n+4(FP), CX 355 MOVL prot+8(FP), DX 356 MOVL flags+12(FP), SI 357 MOVL fd+16(FP), DI 358 MOVL off+20(FP), BP 359 SHRL $12, BP 360 INVOKE_SYSCALL 361 CMPL AX, $0xfffff001 362 JLS ok 363 NOTL AX 364 INCL AX 365 MOVL $0, p+24(FP) 366 MOVL AX, err+28(FP) 367 RET 368 ok: 369 MOVL AX, p+24(FP) 370 MOVL $0, err+28(FP) 371 RET 372 373 TEXT runtime·munmap(SB),NOSPLIT,$0 374 MOVL $SYS_munmap, AX 375 MOVL addr+0(FP), BX 376 MOVL n+4(FP), CX 377 INVOKE_SYSCALL 378 CMPL AX, $0xfffff001 379 JLS 2(PC) 380 INT $3 381 RET 382 383 TEXT runtime·madvise(SB),NOSPLIT,$0 384 MOVL $SYS_madvise, AX 385 MOVL addr+0(FP), BX 386 MOVL n+4(FP), CX 387 MOVL flags+8(FP), DX 388 INVOKE_SYSCALL 389 // ignore failure - maybe pages are locked 390 RET 391 392 // int32 futex(int32 *uaddr, int32 op, int32 val, 393 // struct timespec *timeout, int32 *uaddr2, int32 val2); 394 TEXT runtime·futex(SB),NOSPLIT,$0 395 MOVL $SYS_futex, AX 396 MOVL addr+0(FP), BX 397 MOVL op+4(FP), CX 398 MOVL val+8(FP), DX 399 MOVL ts+12(FP), SI 400 MOVL addr2+16(FP), DI 401 MOVL val3+20(FP), BP 402 INVOKE_SYSCALL 403 MOVL AX, ret+24(FP) 404 RET 405 406 // int32 clone(int32 flags, void *stack, M *mp, G *gp, void (*fn)(void)); 407 TEXT runtime·clone(SB),NOSPLIT,$0 408 MOVL $SYS_clone, AX 409 MOVL flags+0(FP), BX 410 MOVL stk+4(FP), CX 411 MOVL $0, DX // parent tid ptr 412 MOVL $0, DI // child tid ptr 413 414 // Copy mp, gp, fn off parent stack for use by child. 415 SUBL $16, CX 416 MOVL mp+8(FP), SI 417 MOVL SI, 0(CX) 418 MOVL gp+12(FP), SI 419 MOVL SI, 4(CX) 420 MOVL fn+16(FP), SI 421 MOVL SI, 8(CX) 422 MOVL $1234, 12(CX) 423 424 // cannot use CALL 0x10(GS) here, because the stack changes during the 425 // system call (after CALL 0x10(GS), the child is still using the 426 // parent's stack when executing its RET instruction). 427 INT $0x80 428 429 // In parent, return. 430 CMPL AX, $0 431 JEQ 3(PC) 432 MOVL AX, ret+20(FP) 433 RET 434 435 // Paranoia: check that SP is as we expect. 436 MOVL 12(SP), BP 437 CMPL BP, $1234 438 JEQ 2(PC) 439 INT $3 440 441 // Initialize AX to Linux tid 442 MOVL $SYS_gettid, AX 443 INVOKE_SYSCALL 444 445 MOVL 0(SP), BX // m 446 MOVL 4(SP), DX // g 447 MOVL 8(SP), SI // fn 448 449 CMPL BX, $0 450 JEQ nog 451 CMPL DX, $0 452 JEQ nog 453 454 MOVL AX, m_procid(BX) // save tid as m->procid 455 456 // set up ldt 7+id to point at m->tls. 457 LEAL m_tls(BX), BP 458 MOVL m_id(BX), DI 459 ADDL $7, DI // m0 is LDT#7. count up. 460 // setldt(tls#, &tls, sizeof tls) 461 PUSHAL // save registers 462 PUSHL $32 // sizeof tls 463 PUSHL BP // &tls 464 PUSHL DI // tls # 465 CALL runtime·setldt(SB) 466 POPL AX 467 POPL AX 468 POPL AX 469 POPAL 470 471 // Now segment is established. Initialize m, g. 472 get_tls(AX) 473 MOVL DX, g(AX) 474 MOVL BX, g_m(DX) 475 476 CALL runtime·stackcheck(SB) // smashes AX, CX 477 MOVL 0(DX), DX // paranoia; check they are not nil 478 MOVL 0(BX), BX 479 480 // more paranoia; check that stack splitting code works 481 PUSHAL 482 CALL runtime·emptyfunc(SB) 483 POPAL 484 485 nog: 486 CALL SI // fn() 487 CALL exit1<>(SB) 488 MOVL $0x1234, 0x1005 489 490 TEXT runtime·sigaltstack(SB),NOSPLIT,$-8 491 MOVL $SYS_sigaltstack, AX 492 MOVL new+0(FP), BX 493 MOVL old+4(FP), CX 494 INVOKE_SYSCALL 495 CMPL AX, $0xfffff001 496 JLS 2(PC) 497 INT $3 498 RET 499 500 // <asm-i386/ldt.h> 501 // struct user_desc { 502 // unsigned int entry_number; 503 // unsigned long base_addr; 504 // unsigned int limit; 505 // unsigned int seg_32bit:1; 506 // unsigned int contents:2; 507 // unsigned int read_exec_only:1; 508 // unsigned int limit_in_pages:1; 509 // unsigned int seg_not_present:1; 510 // unsigned int useable:1; 511 // }; 512 #define SEG_32BIT 0x01 513 // contents are the 2 bits 0x02 and 0x04. 514 #define CONTENTS_DATA 0x00 515 #define CONTENTS_STACK 0x02 516 #define CONTENTS_CODE 0x04 517 #define READ_EXEC_ONLY 0x08 518 #define LIMIT_IN_PAGES 0x10 519 #define SEG_NOT_PRESENT 0x20 520 #define USEABLE 0x40 521 522 // `-1` means the kernel will pick a TLS entry on the first setldt call, 523 // which happens during runtime init, and that we'll store back the saved 524 // entry and reuse that on subsequent calls when creating new threads. 525 DATA runtime·tls_entry_number+0(SB)/4, $-1 526 GLOBL runtime·tls_entry_number(SB), NOPTR, $4 527 528 // setldt(int entry, int address, int limit) 529 // We use set_thread_area, which mucks with the GDT, instead of modify_ldt, 530 // which would modify the LDT, but is disabled on some kernels. 531 // The name, setldt, is a misnomer, although we leave this name as it is for 532 // the compatibility with other platforms. 533 TEXT runtime·setldt(SB),NOSPLIT,$32 534 MOVL address+4(FP), DX // base address 535 536 #ifdef GOOS_android 537 /* 538 * Same as in sys_darwin_386.s:/ugliness, different constant. 539 * address currently holds m->tls, which must be %gs:0xf8. 540 * See cgo/gcc_android_386.c for the derivation of the constant. 541 */ 542 SUBL $0xf8, DX 543 MOVL DX, 0(DX) 544 #else 545 /* 546 * When linking against the system libraries, 547 * we use its pthread_create and let it set up %gs 548 * for us. When we do that, the private storage 549 * we get is not at 0(GS), but -4(GS). 550 * To insulate the rest of the tool chain from this 551 * ugliness, 8l rewrites 0(TLS) into -4(GS) for us. 552 * To accommodate that rewrite, we translate 553 * the address here and bump the limit to 0xffffffff (no limit) 554 * so that -4(GS) maps to 0(address). 555 * Also, the final 0(GS) (current 4(DX)) has to point 556 * to itself, to mimic ELF. 557 */ 558 ADDL $0x4, DX // address 559 MOVL DX, 0(DX) 560 #endif 561 562 // get entry number 563 MOVL runtime·tls_entry_number(SB), CX 564 565 // set up user_desc 566 LEAL 16(SP), AX // struct user_desc 567 MOVL CX, 0(AX) // unsigned int entry_number 568 MOVL DX, 4(AX) // unsigned long base_addr 569 MOVL $0xfffff, 8(AX) // unsigned int limit 570 MOVL $(SEG_32BIT|LIMIT_IN_PAGES|USEABLE|CONTENTS_DATA), 12(AX) // flag bits 571 572 // call set_thread_area 573 MOVL AX, BX // user_desc 574 MOVL $SYS_set_thread_area, AX 575 // We can't call this via 0x10(GS) because this is called from setldt0 to set that up. 576 INT $0x80 577 578 // breakpoint on error 579 CMPL AX, $0xfffff001 580 JLS 2(PC) 581 INT $3 582 583 // read allocated entry number back out of user_desc 584 LEAL 16(SP), AX // get our user_desc back 585 MOVL 0(AX), AX 586 587 // store entry number if the kernel allocated it 588 CMPL CX, $-1 589 JNE 2(PC) 590 MOVL AX, runtime·tls_entry_number(SB) 591 592 // compute segment selector - (entry*8+3) 593 SHLL $3, AX 594 ADDL $3, AX 595 MOVW AX, GS 596 597 RET 598 599 TEXT runtime·osyield(SB),NOSPLIT,$0 600 MOVL $SYS_sched_yield, AX 601 INVOKE_SYSCALL 602 RET 603 604 TEXT runtime·sched_getaffinity(SB),NOSPLIT,$0 605 MOVL $SYS_sched_getaffinity, AX 606 MOVL pid+0(FP), BX 607 MOVL len+4(FP), CX 608 MOVL buf+8(FP), DX 609 INVOKE_SYSCALL 610 MOVL AX, ret+12(FP) 611 RET 612 613 // int32 runtime·epollcreate(int32 size); 614 TEXT runtime·epollcreate(SB),NOSPLIT,$0 615 MOVL $SYS_epoll_create, AX 616 MOVL size+0(FP), BX 617 INVOKE_SYSCALL 618 MOVL AX, ret+4(FP) 619 RET 620 621 // int32 runtime·epollcreate1(int32 flags); 622 TEXT runtime·epollcreate1(SB),NOSPLIT,$0 623 MOVL $SYS_epoll_create1, AX 624 MOVL flags+0(FP), BX 625 INVOKE_SYSCALL 626 MOVL AX, ret+4(FP) 627 RET 628 629 // func epollctl(epfd, op, fd int32, ev *epollEvent) int 630 TEXT runtime·epollctl(SB),NOSPLIT,$0 631 MOVL $SYS_epoll_ctl, AX 632 MOVL epfd+0(FP), BX 633 MOVL op+4(FP), CX 634 MOVL fd+8(FP), DX 635 MOVL ev+12(FP), SI 636 INVOKE_SYSCALL 637 MOVL AX, ret+16(FP) 638 RET 639 640 // int32 runtime·epollwait(int32 epfd, EpollEvent *ev, int32 nev, int32 timeout); 641 TEXT runtime·epollwait(SB),NOSPLIT,$0 642 MOVL $SYS_epoll_wait, AX 643 MOVL epfd+0(FP), BX 644 MOVL ev+4(FP), CX 645 MOVL nev+8(FP), DX 646 MOVL timeout+12(FP), SI 647 INVOKE_SYSCALL 648 MOVL AX, ret+16(FP) 649 RET 650 651 // void runtime·closeonexec(int32 fd); 652 TEXT runtime·closeonexec(SB),NOSPLIT,$0 653 MOVL $SYS_fcntl, AX 654 MOVL fd+0(FP), BX // fd 655 MOVL $2, CX // F_SETFD 656 MOVL $1, DX // FD_CLOEXEC 657 INVOKE_SYSCALL 658 RET 659 660 // int access(const char *name, int mode) 661 TEXT runtime·access(SB),NOSPLIT,$0 662 MOVL $SYS_access, AX 663 MOVL name+0(FP), BX 664 MOVL mode+4(FP), CX 665 INVOKE_SYSCALL 666 MOVL AX, ret+8(FP) 667 RET 668 669 // int connect(int fd, const struct sockaddr *addr, socklen_t addrlen) 670 TEXT runtime·connect(SB),NOSPLIT,$0-16 671 // connect is implemented as socketcall(NR_socket, 3, *(rest of args)) 672 // stack already should have fd, addr, addrlen. 673 MOVL $SYS_socketcall, AX 674 MOVL $3, BX // connect 675 LEAL fd+0(FP), CX 676 INVOKE_SYSCALL 677 MOVL AX, ret+12(FP) 678 RET 679 680 // int socket(int domain, int type, int protocol) 681 TEXT runtime·socket(SB),NOSPLIT,$0-16 682 // socket is implemented as socketcall(NR_socket, 1, *(rest of args)) 683 // stack already should have domain, type, protocol. 684 MOVL $SYS_socketcall, AX 685 MOVL $1, BX // socket 686 LEAL domain+0(FP), CX 687 INVOKE_SYSCALL 688 MOVL AX, ret+12(FP) 689 RET 690 691 // func sbrk0() uintptr 692 TEXT runtime·sbrk0(SB),NOSPLIT,$0-4 693 // Implemented as brk(NULL). 694 MOVL $SYS_brk, AX 695 MOVL $0, BX // NULL 696 INVOKE_SYSCALL 697 MOVL AX, ret+0(FP) 698 RET