github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/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 // SYS_GETTIMEOFDAY 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 // Sigtramp's job is to call the actual signal handler. 269 // It is called with the following arguments on the stack: 270 // 0(SP) "return address" - ignored 271 // 4(SP) actual handler 272 // 8(SP) siginfo style 273 // 12(SP) signal number 274 // 16(SP) siginfo 275 // 20(SP) context 276 TEXT runtime·sigtramp(SB),NOSPLIT,$20 277 MOVL sig+8(FP), BX 278 MOVL BX, 0(SP) 279 MOVL info+12(FP), BX 280 MOVL BX, 4(SP) 281 MOVL ctx+16(FP), BX 282 MOVL BX, 8(SP) 283 CALL runtime·sigtrampgo(SB) 284 285 // call sigreturn 286 MOVL ctx+16(FP), CX 287 MOVL infostyle+4(FP), BX 288 MOVL $0, 0(SP) // "caller PC" - ignored 289 MOVL CX, 4(SP) 290 MOVL BX, 8(SP) 291 MOVL $184, AX // sigreturn(ucontext, infostyle) 292 INT $0x80 293 MOVL $0xf1, 0xf1 // crash 294 RET 295 296 TEXT runtime·sigaltstack(SB),NOSPLIT,$0 297 MOVL $53, AX 298 INT $0x80 299 JAE 2(PC) 300 MOVL $0xf1, 0xf1 // crash 301 RET 302 303 TEXT runtime·usleep(SB),NOSPLIT,$32 304 MOVL $0, DX 305 MOVL usec+0(FP), AX 306 MOVL $1000000, CX 307 DIVL CX 308 MOVL AX, 24(SP) // sec 309 MOVL DX, 28(SP) // usec 310 311 // select(0, 0, 0, 0, &tv) 312 MOVL $0, 0(SP) // "return PC" - ignored 313 MOVL $0, 4(SP) 314 MOVL $0, 8(SP) 315 MOVL $0, 12(SP) 316 MOVL $0, 16(SP) 317 LEAL 24(SP), AX 318 MOVL AX, 20(SP) 319 MOVL $93, AX 320 INT $0x80 321 RET 322 323 // func bsdthread_create(stk, arg unsafe.Pointer, fn uintptr) int32 324 // System call args are: func arg stack pthread flags. 325 TEXT runtime·bsdthread_create(SB),NOSPLIT,$32 326 MOVL $360, AX 327 // 0(SP) is where the caller PC would be; kernel skips it 328 MOVL fn+8(FP), BX 329 MOVL BX, 4(SP) // func 330 MOVL arg+4(FP), BX 331 MOVL BX, 8(SP) // arg 332 MOVL stk+0(FP), BX 333 MOVL BX, 12(SP) // stack 334 MOVL $0, 16(SP) // pthread 335 MOVL $0x1000000, 20(SP) // flags = PTHREAD_START_CUSTOM 336 INT $0x80 337 JAE 4(PC) 338 NEGL AX 339 MOVL AX, ret+12(FP) 340 RET 341 MOVL $0, AX 342 MOVL AX, ret+12(FP) 343 RET 344 345 // The thread that bsdthread_create creates starts executing here, 346 // because we registered this function using bsdthread_register 347 // at startup. 348 // AX = "pthread" (= 0x0) 349 // BX = mach thread port 350 // CX = "func" (= fn) 351 // DX = "arg" (= m) 352 // DI = stack top 353 // SI = flags (= 0x1000000) 354 // SP = stack - C_32_STK_ALIGN 355 TEXT runtime·bsdthread_start(SB),NOSPLIT,$0 356 // set up ldt 7+id to point at m->tls. 357 LEAL m_tls(DX), BP 358 MOVL m_id(DX), DI 359 ADDL $7, DI // m0 is LDT#7. count up. 360 // setldt(tls#, &tls, sizeof tls) 361 PUSHAL // save registers 362 PUSHL $32 // sizeof tls 363 PUSHL BP // &tls 364 PUSHL DI // tls # 365 CALL runtime·setldt(SB) 366 POPL AX 367 POPL AX 368 POPL AX 369 POPAL 370 371 // Now segment is established. Initialize m, g. 372 get_tls(BP) 373 MOVL m_g0(DX), AX 374 MOVL AX, g(BP) 375 MOVL DX, g_m(AX) 376 MOVL BX, m_procid(DX) // m->procid = thread port (for debuggers) 377 CALL runtime·stackcheck(SB) // smashes AX 378 CALL CX // fn() 379 CALL runtime·exit1(SB) 380 RET 381 382 // func bsdthread_register() int32 383 // registers callbacks for threadstart (see bsdthread_create above 384 // and wqthread and pthsize (not used). returns 0 on success. 385 TEXT runtime·bsdthread_register(SB),NOSPLIT,$40 386 MOVL $366, AX 387 // 0(SP) is where kernel expects caller PC; ignored 388 MOVL $runtime·bsdthread_start(SB), 4(SP) // threadstart 389 MOVL $0, 8(SP) // wqthread, not used by us 390 MOVL $0, 12(SP) // pthsize, not used by us 391 MOVL $0, 16(SP) // dummy_value [sic] 392 MOVL $0, 20(SP) // targetconc_ptr 393 MOVL $0, 24(SP) // dispatchqueue_offset 394 INT $0x80 395 JAE 4(PC) 396 NEGL AX 397 MOVL AX, ret+0(FP) 398 RET 399 MOVL $0, AX 400 MOVL AX, ret+0(FP) 401 RET 402 403 // Invoke Mach system call. 404 // Assumes system call number in AX, 405 // caller PC on stack, caller's caller PC next, 406 // and then the system call arguments. 407 // 408 // Can be used for BSD too, but we don't, 409 // because if you use this interface the BSD 410 // system call numbers need an extra field 411 // in the high 16 bits that seems to be the 412 // argument count in bytes but is not always. 413 // INT $0x80 works fine for those. 414 TEXT runtime·sysenter(SB),NOSPLIT,$0 415 POPL DX 416 MOVL SP, CX 417 BYTE $0x0F; BYTE $0x34; // SYSENTER 418 // returns to DX with SP set to CX 419 420 TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0 421 MOVL $-31, AX 422 CALL runtime·sysenter(SB) 423 MOVL AX, ret+28(FP) 424 RET 425 426 TEXT runtime·mach_reply_port(SB),NOSPLIT,$0 427 MOVL $-26, AX 428 CALL runtime·sysenter(SB) 429 MOVL AX, ret+0(FP) 430 RET 431 432 TEXT runtime·mach_task_self(SB),NOSPLIT,$0 433 MOVL $-28, AX 434 CALL runtime·sysenter(SB) 435 MOVL AX, ret+0(FP) 436 RET 437 438 // Mach provides trap versions of the semaphore ops, 439 // instead of requiring the use of RPC. 440 441 // func mach_semaphore_wait(sema uint32) int32 442 TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0 443 MOVL $-36, AX 444 CALL runtime·sysenter(SB) 445 MOVL AX, ret+4(FP) 446 RET 447 448 // func mach_semaphore_timedwait(sema, sec, nsec uint32) int32 449 TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0 450 MOVL $-38, AX 451 CALL runtime·sysenter(SB) 452 MOVL AX, ret+12(FP) 453 RET 454 455 // func mach_semaphore_signal(sema uint32) int32 456 TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0 457 MOVL $-33, AX 458 CALL runtime·sysenter(SB) 459 MOVL AX, ret+4(FP) 460 RET 461 462 // func mach_semaphore_signal_all(sema uint32) int32 463 TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0 464 MOVL $-34, AX 465 CALL runtime·sysenter(SB) 466 MOVL AX, ret+4(FP) 467 RET 468 469 // func setldt(entry int, address int, limit int) 470 // entry and limit are ignored. 471 TEXT runtime·setldt(SB),NOSPLIT,$32 472 MOVL address+4(FP), BX // aka base 473 474 /* 475 * When linking against the system libraries, 476 * we use its pthread_create and let it set up %gs 477 * for us. When we do that, the private storage 478 * we get is not at 0(GS) but at 0x468(GS). 479 * 8l rewrites 0(TLS) into 0x468(GS) for us. 480 * To accommodate that rewrite, we translate the 481 * address and limit here so that 0x468(GS) maps to 0(address). 482 * 483 * See cgo/gcc_darwin_386.c:/468 for the derivation 484 * of the constant. 485 */ 486 SUBL $0x468, BX 487 488 /* 489 * Must set up as USER_CTHREAD segment because 490 * Darwin forces that value into %gs for signal handlers, 491 * and if we don't set one up, we'll get a recursive 492 * fault trying to get into the signal handler. 493 * Since we have to set one up anyway, it might as 494 * well be the value we want. So don't bother with 495 * i386_set_ldt. 496 */ 497 MOVL BX, 4(SP) 498 MOVL $3, AX // thread_fast_set_cthread_self - machdep call #3 499 INT $0x82 // sic: 0x82, not 0x80, for machdep call 500 501 XORL AX, AX 502 MOVW GS, AX 503 RET 504 505 TEXT runtime·sysctl(SB),NOSPLIT,$0 506 MOVL $202, AX 507 INT $0x80 508 JAE 4(PC) 509 NEGL AX 510 MOVL AX, ret+24(FP) 511 RET 512 MOVL $0, AX 513 MOVL AX, ret+24(FP) 514 RET 515 516 // func kqueue() int32 517 TEXT runtime·kqueue(SB),NOSPLIT,$0 518 MOVL $362, AX 519 INT $0x80 520 JAE 2(PC) 521 NEGL AX 522 MOVL AX, ret+0(FP) 523 RET 524 525 // func kevent(kq int32, ch *keventt, nch int32, ev *keventt, nev int32, ts *timespec) int32 526 TEXT runtime·kevent(SB),NOSPLIT,$0 527 MOVL $363, AX 528 INT $0x80 529 JAE 2(PC) 530 NEGL AX 531 MOVL AX, ret+24(FP) 532 RET 533 534 // func closeonexec(fd int32) 535 TEXT runtime·closeonexec(SB),NOSPLIT,$32 536 MOVL $92, AX // fcntl 537 // 0(SP) is where the caller PC would be; kernel skips it 538 MOVL fd+0(FP), BX 539 MOVL BX, 4(SP) // fd 540 MOVL $2, 8(SP) // F_SETFD 541 MOVL $1, 12(SP) // FD_CLOEXEC 542 INT $0x80 543 JAE 2(PC) 544 NEGL AX 545 RET