github.com/euank/go@v0.0.0-20160829210321-495514729181/src/runtime/sys_darwin_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 // System calls and other sys.stuff for 386, Darwin 6 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228 7 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers. 8 9 #include "go_asm.h" 10 #include "go_tls.h" 11 #include "textflag.h" 12 13 // Exit the entire program (like C exit) 14 TEXT runtime·exit(SB),NOSPLIT,$0 15 MOVL $1, AX 16 INT $0x80 17 MOVL $0xf1, 0xf1 // crash 18 RET 19 20 // Exit this OS thread (like pthread_exit, which eventually 21 // calls __bsdthread_terminate). 22 TEXT runtime·exit1(SB),NOSPLIT,$0 23 MOVL $361, AX 24 INT $0x80 25 JAE 2(PC) 26 MOVL $0xf1, 0xf1 // crash 27 RET 28 29 TEXT runtime·open(SB),NOSPLIT,$0 30 MOVL $5, AX 31 INT $0x80 32 JAE 2(PC) 33 MOVL $-1, AX 34 MOVL AX, ret+12(FP) 35 RET 36 37 TEXT runtime·closefd(SB),NOSPLIT,$0 38 MOVL $6, AX 39 INT $0x80 40 JAE 2(PC) 41 MOVL $-1, AX 42 MOVL AX, ret+4(FP) 43 RET 44 45 TEXT runtime·read(SB),NOSPLIT,$0 46 MOVL $3, AX 47 INT $0x80 48 JAE 2(PC) 49 MOVL $-1, AX 50 MOVL AX, ret+12(FP) 51 RET 52 53 TEXT runtime·write(SB),NOSPLIT,$0 54 MOVL $4, AX 55 INT $0x80 56 JAE 2(PC) 57 MOVL $-1, AX 58 MOVL AX, ret+12(FP) 59 RET 60 61 TEXT runtime·raise(SB),NOSPLIT,$0 62 // Ideally we'd send the signal to the current thread, 63 // not the whole process, but that's too hard on OS X. 64 JMP runtime·raiseproc(SB) 65 66 TEXT runtime·raiseproc(SB),NOSPLIT,$16 67 MOVL $20, AX // getpid 68 INT $0x80 69 MOVL AX, 4(SP) // pid 70 MOVL sig+0(FP), AX 71 MOVL AX, 8(SP) // signal 72 MOVL $1, 12(SP) // posix 73 MOVL $37, AX // kill 74 INT $0x80 75 RET 76 77 TEXT runtime·mmap(SB),NOSPLIT,$0 78 MOVL $197, AX 79 INT $0x80 80 MOVL AX, ret+24(FP) 81 RET 82 83 TEXT runtime·madvise(SB),NOSPLIT,$0 84 MOVL $75, AX 85 INT $0x80 86 // ignore failure - maybe pages are locked 87 RET 88 89 TEXT runtime·munmap(SB),NOSPLIT,$0 90 MOVL $73, AX 91 INT $0x80 92 JAE 2(PC) 93 MOVL $0xf1, 0xf1 // crash 94 RET 95 96 TEXT runtime·setitimer(SB),NOSPLIT,$0 97 MOVL $83, AX 98 INT $0x80 99 RET 100 101 // OS X comm page time offsets 102 // http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h 103 #define cpu_capabilities 0x20 104 #define nt_tsc_base 0x50 105 #define nt_scale 0x58 106 #define nt_shift 0x5c 107 #define nt_ns_base 0x60 108 #define nt_generation 0x68 109 #define gtod_generation 0x6c 110 #define gtod_ns_base 0x70 111 #define gtod_sec_base 0x78 112 113 // called from assembly 114 // 64-bit unix nanoseconds returned in DX:AX. 115 // I'd much rather write this in C but we need 116 // assembly for the 96-bit multiply and RDTSC. 117 TEXT runtime·now(SB),NOSPLIT,$40 118 MOVL $0xffff0000, BP /* comm page base */ 119 120 // Test for slow CPU. If so, the math is completely 121 // different, and unimplemented here, so use the 122 // system call. 123 MOVL cpu_capabilities(BP), AX 124 TESTL $0x4000, AX 125 JNZ systime 126 127 // Loop trying to take a consistent snapshot 128 // of the time parameters. 129 timeloop: 130 MOVL gtod_generation(BP), BX 131 TESTL BX, BX 132 JZ systime 133 MOVL nt_generation(BP), CX 134 TESTL CX, CX 135 JZ timeloop 136 RDTSC 137 MOVL nt_tsc_base(BP), SI 138 MOVL (nt_tsc_base+4)(BP), DI 139 MOVL SI, 0(SP) 140 MOVL DI, 4(SP) 141 MOVL nt_scale(BP), SI 142 MOVL SI, 8(SP) 143 MOVL nt_ns_base(BP), SI 144 MOVL (nt_ns_base+4)(BP), DI 145 MOVL SI, 12(SP) 146 MOVL DI, 16(SP) 147 CMPL nt_generation(BP), CX 148 JNE timeloop 149 MOVL gtod_ns_base(BP), SI 150 MOVL (gtod_ns_base+4)(BP), DI 151 MOVL SI, 20(SP) 152 MOVL DI, 24(SP) 153 MOVL gtod_sec_base(BP), SI 154 MOVL (gtod_sec_base+4)(BP), DI 155 MOVL SI, 28(SP) 156 MOVL DI, 32(SP) 157 CMPL gtod_generation(BP), BX 158 JNE timeloop 159 160 // Gathered all the data we need. Compute time. 161 // ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9 162 // The multiply and shift extracts the top 64 bits of the 96-bit product. 163 SUBL 0(SP), AX // DX:AX = (tsc - nt_tsc_base) 164 SBBL 4(SP), DX 165 166 // We have x = tsc - nt_tsc_base - DX:AX to be 167 // multiplied by y = nt_scale = 8(SP), keeping the top 64 bits of the 96-bit product. 168 // x*y = (x&0xffffffff)*y + (x&0xffffffff00000000)*y 169 // (x*y)>>32 = ((x&0xffffffff)*y)>>32 + (x>>32)*y 170 MOVL DX, CX // SI = (x&0xffffffff)*y >> 32 171 MOVL $0, DX 172 MULL 8(SP) 173 MOVL DX, SI 174 175 MOVL CX, AX // DX:AX = (x>>32)*y 176 MOVL $0, DX 177 MULL 8(SP) 178 179 ADDL SI, AX // DX:AX += (x&0xffffffff)*y >> 32 180 ADCL $0, DX 181 182 // DX:AX is now ((tsc - nt_tsc_base) * nt_scale) >> 32. 183 ADDL 12(SP), AX // DX:AX += nt_ns_base 184 ADCL 16(SP), DX 185 SUBL 20(SP), AX // DX:AX -= gtod_ns_base 186 SBBL 24(SP), DX 187 MOVL AX, SI // DI:SI = DX:AX 188 MOVL DX, DI 189 MOVL 28(SP), AX // DX:AX = gtod_sec_base*1e9 190 MOVL 32(SP), DX 191 MOVL $1000000000, CX 192 MULL CX 193 ADDL SI, AX // DX:AX += DI:SI 194 ADCL DI, DX 195 RET 196 197 systime: 198 // Fall back to system call (usually first call in this thread) 199 LEAL 16(SP), AX // must be non-nil, unused 200 MOVL AX, 4(SP) 201 MOVL $0, 8(SP) // time zone pointer 202 MOVL $0, 12(SP) // required as of Sierra; Issue 16570 203 MOVL $116, AX 204 INT $0x80 205 CMPL AX, $0 206 JNE inreg 207 MOVL 16(SP), AX 208 MOVL 20(SP), DX 209 inreg: 210 // sec is in AX, usec in DX 211 // convert to DX:AX nsec 212 MOVL DX, BX 213 MOVL $1000000000, CX 214 MULL CX 215 IMULL $1000, BX 216 ADDL BX, AX 217 ADCL $0, DX 218 RET 219 220 // func now() (sec int64, nsec int32) 221 TEXT time·now(SB),NOSPLIT,$0 222 CALL runtime·now(SB) 223 MOVL $1000000000, CX 224 DIVL CX 225 MOVL AX, sec+0(FP) 226 MOVL $0, sec+4(FP) 227 MOVL DX, nsec+8(FP) 228 RET 229 230 // func nanotime() int64 231 TEXT runtime·nanotime(SB),NOSPLIT,$0 232 CALL runtime·now(SB) 233 MOVL AX, ret_lo+0(FP) 234 MOVL DX, ret_hi+4(FP) 235 RET 236 237 TEXT runtime·sigprocmask(SB),NOSPLIT,$0 238 MOVL $329, AX // pthread_sigmask (on OS X, sigprocmask==entire process) 239 INT $0x80 240 JAE 2(PC) 241 MOVL $0xf1, 0xf1 // crash 242 RET 243 244 TEXT runtime·sigaction(SB),NOSPLIT,$0 245 MOVL $46, AX 246 INT $0x80 247 JAE 2(PC) 248 MOVL $0xf1, 0xf1 // crash 249 RET 250 251 TEXT runtime·sigfwd(SB),NOSPLIT,$0-16 252 MOVL fn+0(FP), AX 253 MOVL sig+4(FP), BX 254 MOVL info+8(FP), CX 255 MOVL ctx+12(FP), DX 256 MOVL SP, SI 257 SUBL $32, SP // align stack; handler might be C code 258 ANDL $~15, SP 259 MOVL BX, 0(SP) 260 MOVL CX, 4(SP) 261 MOVL DX, 8(SP) 262 MOVL SI, 12(SP) 263 CALL AX 264 MOVL 12(SP), AX 265 MOVL AX, SP 266 RET 267 268 TEXT runtime·sigreturn(SB),NOSPLIT,$12-8 269 MOVL ctx+0(FP), CX 270 MOVL infostyle+4(FP), BX 271 MOVL $0, 0(SP) // "caller PC" - ignored 272 MOVL CX, 4(SP) 273 MOVL BX, 8(SP) 274 MOVL $184, AX // sigreturn(ucontext, infostyle) 275 INT $0x80 276 MOVL $0xf1, 0xf1 // crash 277 RET 278 279 // Sigtramp's job is to call the actual signal handler. 280 // It is called with the following arguments on the stack: 281 // 0(SP) "return address" - ignored 282 // 4(SP) actual handler 283 // 8(SP) siginfo style 284 // 12(SP) signal number 285 // 16(SP) siginfo 286 // 20(SP) context 287 TEXT runtime·sigtramp(SB),NOSPLIT,$20 288 MOVL fn+0(FP), BX 289 MOVL BX, 0(SP) 290 MOVL infostyle+4(FP), BX 291 MOVL BX, 4(SP) 292 MOVL sig+8(FP), BX 293 MOVL BX, 8(SP) 294 MOVL info+12(FP), BX 295 MOVL BX, 12(SP) 296 MOVL ctx+16(FP), BX 297 MOVL BX, 16(SP) 298 CALL runtime·sigtrampgo(SB) 299 300 // call sigreturn 301 MOVL ctx+16(FP), CX 302 MOVL infostyle+4(FP), BX 303 MOVL $0, 0(SP) // "caller PC" - ignored 304 MOVL CX, 4(SP) 305 MOVL BX, 8(SP) 306 MOVL $184, AX // sigreturn(ucontext, infostyle) 307 INT $0x80 308 MOVL $0xf1, 0xf1 // crash 309 RET 310 311 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 312 MOVL $53, AX 313 INT $0x80 314 JAE 2(PC) 315 MOVL $0xf1, 0xf1 // crash 316 RET 317 318 TEXT runtime·usleep(SB),NOSPLIT,$32 319 MOVL $0, DX 320 MOVL usec+0(FP), AX 321 MOVL $1000000, CX 322 DIVL CX 323 MOVL AX, 24(SP) // sec 324 MOVL DX, 28(SP) // usec 325 326 // select(0, 0, 0, 0, &tv) 327 MOVL $0, 0(SP) // "return PC" - ignored 328 MOVL $0, 4(SP) 329 MOVL $0, 8(SP) 330 MOVL $0, 12(SP) 331 MOVL $0, 16(SP) 332 LEAL 24(SP), AX 333 MOVL AX, 20(SP) 334 MOVL $93, AX 335 INT $0x80 336 RET 337 338 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 339 // System call args are: func arg stack pthread flags. 340 TEXT runtime·bsdthread_create(SB),NOSPLIT,$32 341 MOVL $360, AX 342 // 0(SP) is where the caller PC would be; kernel skips it 343 MOVL fn+8(FP), BX 344 MOVL BX, 4(SP) // func 345 MOVL arg+4(FP), BX 346 MOVL BX, 8(SP) // arg 347 MOVL stk+0(FP), BX 348 MOVL BX, 12(SP) // stack 349 MOVL $0, 16(SP) // pthread 350 MOVL $0x1000000, 20(SP) // flags = PTHREAD_START_CUSTOM 351 INT $0x80 352 JAE 4(PC) 353 NEGL AX 354 MOVL AX, ret+12(FP) 355 RET 356 MOVL $0, AX 357 MOVL AX, ret+12(FP) 358 RET 359 360 // The thread that bsdthread_create creates starts executing here, 361 // because we registered this function using bsdthread_register 362 // at startup. 363 // AX = "pthread" (= 0x0) 364 // BX = mach thread port 365 // CX = "func" (= fn) 366 // DX = "arg" (= m) 367 // DI = stack top 368 // SI = flags (= 0x1000000) 369 // SP = stack - C_32_STK_ALIGN 370 TEXT runtime·bsdthread_start(SB),NOSPLIT,$0 371 // set up ldt 7+id to point at m->tls. 372 LEAL m_tls(DX), BP 373 MOVL m_id(DX), DI 374 ADDL $7, DI // m0 is LDT#7. count up. 375 // setldt(tls#, &tls, sizeof tls) 376 PUSHAL // save registers 377 PUSHL $32 // sizeof tls 378 PUSHL BP // &tls 379 PUSHL DI // tls # 380 CALL runtime·setldt(SB) 381 POPL AX 382 POPL AX 383 POPL AX 384 POPAL 385 386 // Now segment is established. Initialize m, g. 387 get_tls(BP) 388 MOVL m_g0(DX), AX 389 MOVL AX, g(BP) 390 MOVL DX, g_m(AX) 391 MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers) 392 CALL runtime·stackcheck(SB) // smashes AX 393 CALL CX // fn() 394 CALL runtime·exit1(SB) 395 RET 396 397 // func bsdthread_register() int32 398 // registers callbacks for threadstart (see bsdthread_create above 399 // and wqthread and pthsize (not used). returns 0 on success. 400 TEXT runtime·bsdthread_register(SB),NOSPLIT,$40 401 MOVL $366, AX 402 // 0(SP) is where kernel expects caller PC; ignored 403 MOVL $runtime·bsdthread_start(SB), 4(SP) // threadstart 404 MOVL $0, 8(SP) // wqthread, not used by us 405 MOVL $0, 12(SP) // pthsize, not used by us 406 MOVL $0, 16(SP) // dummy_value [sic] 407 MOVL $0, 20(SP) // targetconc_ptr 408 MOVL $0, 24(SP) // dispatchqueue_offset 409 INT $0x80 410 JAE 4(PC) 411 NEGL AX 412 MOVL AX, ret+0(FP) 413 RET 414 MOVL $0, AX 415 MOVL AX, ret+0(FP) 416 RET 417 418 // Invoke Mach system call. 419 // Assumes system call number in AX, 420 // caller PC on stack, caller's caller PC next, 421 // and then the system call arguments. 422 // 423 // Can be used for BSD too, but we don't, 424 // because if you use this interface the BSD 425 // system call numbers need an extra field 426 // in the high 16 bits that seems to be the 427 // argument count in bytes but is not always. 428 // INT $0x80 works fine for those. 429 TEXT runtime·sysenter(SB),NOSPLIT,$0 430 POPL DX 431 MOVL SP, CX 432 BYTE $0x0F; BYTE $0x34; // SYSENTER 433 // returns to DX with SP set to CX 434 435 TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0 436 MOVL $-31, AX 437 CALL runtime·sysenter(SB) 438 MOVL AX, ret+28(FP) 439 RET 440 441 TEXT runtime·mach_reply_port(SB),NOSPLIT,$0 442 MOVL $-26, AX 443 CALL runtime·sysenter(SB) 444 MOVL AX, ret+0(FP) 445 RET 446 447 TEXT runtime·mach_task_self(SB),NOSPLIT,$0 448 MOVL $-28, AX 449 CALL runtime·sysenter(SB) 450 MOVL AX, ret+0(FP) 451 RET 452 453 // Mach provides trap versions of the semaphore ops, 454 // instead of requiring the use of RPC. 455 456 // func mach_semaphore_wait(sema uint32) int32 457 TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0 458 MOVL $-36, AX 459 CALL runtime·sysenter(SB) 460 MOVL AX, ret+4(FP) 461 RET 462 463 // func mach_semaphore_timedwait(sema, sec, nsec uint32) int32 464 TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0 465 MOVL $-38, AX 466 CALL runtime·sysenter(SB) 467 MOVL AX, ret+12(FP) 468 RET 469 470 // func mach_semaphore_signal(sema uint32) int32 471 TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0 472 MOVL $-33, AX 473 CALL runtime·sysenter(SB) 474 MOVL AX, ret+4(FP) 475 RET 476 477 // func mach_semaphore_signal_all(sema uint32) int32 478 TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0 479 MOVL $-34, AX 480 CALL runtime·sysenter(SB) 481 MOVL AX, ret+4(FP) 482 RET 483 484 // func setldt(entry int, address int, limit int) 485 // entry and limit are ignored. 486 TEXT runtime·setldt(SB),NOSPLIT,$32 487 MOVL address+4(FP), BX // aka base 488 489 /* 490 * When linking against the system libraries, 491 * we use its pthread_create and let it set up %gs 492 * for us. When we do that, the private storage 493 * we get is not at 0(GS) but at 0x468(GS). 494 * 8l rewrites 0(TLS) into 0x468(GS) for us. 495 * To accommodate that rewrite, we translate the 496 * address and limit here so that 0x468(GS) maps to 0(address). 497 * 498 * See cgo/gcc_darwin_386.c:/468 for the derivation 499 * of the constant. 500 */ 501 SUBL $0x468, BX 502 503 /* 504 * Must set up as USER_CTHREAD segment because 505 * Darwin forces that value into %gs for signal handlers, 506 * and if we don't set one up, we'll get a recursive 507 * fault trying to get into the signal handler. 508 * Since we have to set one up anyway, it might as 509 * well be the value we want. So don't bother with 510 * i386_set_ldt. 511 */ 512 MOVL BX, 4(SP) 513 MOVL $3, AX // thread_fast_set_cthread_self - machdep call #3 514 INT $0x82 // sic: 0x82, not 0x80, for machdep call 515 516 XORL AX, AX 517 MOVW GS, AX 518 RET 519 520 TEXT runtime·sysctl(SB),NOSPLIT,$0 521 MOVL $202, AX 522 INT $0x80 523 JAE 4(PC) 524 NEGL AX 525 MOVL AX, ret+24(FP) 526 RET 527 MOVL $0, AX 528 MOVL AX, ret+24(FP) 529 RET 530 531 // func kqueue() int32 532 TEXT runtime·kqueue(SB),NOSPLIT,$0 533 MOVL $362, AX 534 INT $0x80 535 JAE 2(PC) 536 NEGL AX 537 MOVL AX, ret+0(FP) 538 RET 539 540 // func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 541 TEXT runtime·kevent(SB),NOSPLIT,$0 542 MOVL $363, AX 543 INT $0x80 544 JAE 2(PC) 545 NEGL AX 546 MOVL AX, ret+24(FP) 547 RET 548 549 // func closeonexec(fd int32) 550 TEXT runtime·closeonexec(SB),NOSPLIT,$32 551 MOVL $92, AX // fcntl 552 // 0(SP) is where the caller PC would be; kernel skips it 553 MOVL fd+0(FP), BX 554 MOVL BX, 4(SP) // fd 555 MOVL $2, 8(SP) // F_SETFD 556 MOVL $1, 12(SP) // FD_CLOEXEC 557 INT $0x80 558 JAE 2(PC) 559 NEGL AX 560 RET