]> Cypherpunks.ru repositories - gostls13.git/blob - src/runtime/sys_darwin_amd64.s
[dev.cc] all: merge dev.power64 (7667e41f3ced) into dev.cc
[gostls13.git] / src / runtime / sys_darwin_amd64.s
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 AMD64, Darwin
7 // See http://fxr.watson.org/fxr/source/bsd/kern/syscalls.c?v=xnu-1228
8 // or /usr/include/sys/syscall.h (on a Mac) for system call numbers.
9 //
10 // The low 24 bits are the system call number.
11 // The high 8 bits specify the kind of system call: 1=Mach, 2=BSD, 3=Machine-Dependent.
12 //
13
14 #include "go_asm.h"
15 #include "go_tls.h"
16 #include "textflag.h"
17
18 // Exit the entire program (like C exit)
19 TEXT runtime·exit(SB),NOSPLIT,$0
20         MOVL    code+0(FP), DI          // arg 1 exit status
21         MOVL    $(0x2000000+1), AX      // syscall entry
22         SYSCALL
23         MOVL    $0xf1, 0xf1  // crash
24         RET
25
26 // Exit this OS thread (like pthread_exit, which eventually
27 // calls __bsdthread_terminate).
28 TEXT runtime·exit1(SB),NOSPLIT,$0
29         MOVL    code+0(FP), DI          // arg 1 exit status
30         MOVL    $(0x2000000+361), AX    // syscall entry
31         SYSCALL
32         MOVL    $0xf1, 0xf1  // crash
33         RET
34
35 TEXT runtime·open(SB),NOSPLIT,$0
36         MOVQ    name+0(FP), DI          // arg 1 pathname
37         MOVL    mode+8(FP), SI          // arg 2 flags
38         MOVL    perm+12(FP), DX         // arg 3 mode
39         MOVL    $(0x2000000+5), AX      // syscall entry
40         SYSCALL
41         MOVL    AX, ret+16(FP)
42         RET
43
44 TEXT runtime·close(SB),NOSPLIT,$0
45         MOVL    fd+0(FP), DI            // arg 1 fd
46         MOVL    $(0x2000000+6), AX      // syscall entry
47         SYSCALL
48         MOVL    AX, ret+8(FP)
49         RET
50
51 TEXT runtime·read(SB),NOSPLIT,$0
52         MOVL    fd+0(FP), DI            // arg 1 fd
53         MOVQ    p+8(FP), SI             // arg 2 buf
54         MOVL    n+16(FP), DX            // arg 3 count
55         MOVL    $(0x2000000+3), AX      // syscall entry
56         SYSCALL
57         MOVL    AX, ret+24(FP)
58         RET
59
60 TEXT runtime·write(SB),NOSPLIT,$0
61         MOVQ    fd+0(FP), DI            // arg 1 fd
62         MOVQ    p+8(FP), SI             // arg 2 buf
63         MOVL    n+16(FP), DX            // arg 3 count
64         MOVL    $(0x2000000+4), AX      // syscall entry
65         SYSCALL
66         MOVL    AX, ret+24(FP)
67         RET
68
69 TEXT runtime·raise(SB),NOSPLIT,$24
70         MOVL    $(0x2000000+20), AX // getpid
71         SYSCALL
72         MOVQ    AX, DI  // arg 1 - pid
73         MOVL    sig+0(FP), SI   // arg 2 - signal
74         MOVL    $1, DX  // arg 3 - posix
75         MOVL    $(0x2000000+37), AX // kill
76         SYSCALL
77         RET
78
79 TEXT runtime·setitimer(SB), NOSPLIT, $0
80         MOVL    mode+0(FP), DI
81         MOVQ    new+8(FP), SI
82         MOVQ    old+16(FP), DX
83         MOVL    $(0x2000000+83), AX     // syscall entry
84         SYSCALL
85         RET
86
87 TEXT runtime·madvise(SB), NOSPLIT, $0
88         MOVQ    addr+0(FP), DI          // arg 1 addr
89         MOVQ    n+8(FP), SI             // arg 2 len
90         MOVL    flags+16(FP), DX                // arg 3 advice
91         MOVL    $(0x2000000+75), AX     // syscall entry madvise
92         SYSCALL
93         // ignore failure - maybe pages are locked
94         RET
95
96 // OS X comm page time offsets
97 // http://www.opensource.apple.com/source/xnu/xnu-1699.26.8/osfmk/i386/cpu_capabilities.h
98 #define nt_tsc_base     0x50
99 #define nt_scale        0x58
100 #define nt_shift        0x5c
101 #define nt_ns_base      0x60
102 #define nt_generation   0x68
103 #define gtod_generation 0x6c
104 #define gtod_ns_base    0x70
105 #define gtod_sec_base   0x78
106
107 TEXT nanotime<>(SB), NOSPLIT, $32
108         MOVQ    $0x7fffffe00000, BP     /* comm page base */
109         // Loop trying to take a consistent snapshot
110         // of the time parameters.
111 timeloop:
112         MOVL    gtod_generation(BP), R8
113         TESTL   R8, R8
114         JZ      systime
115         MOVL    nt_generation(BP), R9
116         TESTL   R9, R9
117         JZ      timeloop
118         RDTSC
119         MOVQ    nt_tsc_base(BP), R10
120         MOVL    nt_scale(BP), R11
121         MOVQ    nt_ns_base(BP), R12
122         CMPL    nt_generation(BP), R9
123         JNE     timeloop
124         MOVQ    gtod_ns_base(BP), R13
125         MOVQ    gtod_sec_base(BP), R14
126         CMPL    gtod_generation(BP), R8
127         JNE     timeloop
128
129         // Gathered all the data we need. Compute time.
130         //      ((tsc - nt_tsc_base) * nt_scale) >> 32 + nt_ns_base - gtod_ns_base + gtod_sec_base*1e9
131         // The multiply and shift extracts the top 64 bits of the 96-bit product.
132         SHLQ    $32, DX
133         ADDQ    DX, AX
134         SUBQ    R10, AX
135         MULQ    R11
136         SHRQ    $32, AX:DX
137         ADDQ    R12, AX
138         SUBQ    R13, AX
139         IMULQ   $1000000000, R14
140         ADDQ    R14, AX
141         RET
142
143 systime:
144         // Fall back to system call (usually first call in this thread).
145         MOVQ    SP, DI  // must be non-nil, unused
146         MOVQ    $0, SI
147         MOVL    $(0x2000000+116), AX
148         SYSCALL
149         // sec is in AX, usec in DX
150         // return nsec in AX
151         IMULQ   $1000000000, AX
152         IMULQ   $1000, DX
153         ADDQ    DX, AX
154         RET
155
156 TEXT runtime·nanotime(SB),NOSPLIT,$0-8
157         CALL    nanotime<>(SB)
158         MOVQ    AX, ret+0(FP)
159         RET
160
161 // func now() (sec int64, nsec int32)
162 TEXT time·now(SB),NOSPLIT,$0-12
163         CALL    nanotime<>(SB)
164
165         // generated code for
166         //      func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
167         // adapted to reduce duplication
168         MOVQ    AX, CX
169         MOVQ    $1360296554856532783, AX
170         MULQ    CX
171         ADDQ    CX, DX
172         RCRQ    $1, DX
173         SHRQ    $29, DX
174         MOVQ    DX, sec+0(FP)
175         IMULQ   $1000000000, DX
176         SUBQ    DX, CX
177         MOVL    CX, nsec+8(FP)
178         RET
179
180 TEXT runtime·sigprocmask(SB),NOSPLIT,$0
181         MOVL    sig+0(FP), DI
182         MOVQ    new+8(FP), SI
183         MOVQ    old+16(FP), DX
184         MOVL    $(0x2000000+329), AX  // pthread_sigmask (on OS X, sigprocmask==entire process)
185         SYSCALL
186         JCC     2(PC)
187         MOVL    $0xf1, 0xf1  // crash
188         RET
189
190 TEXT runtime·sigaction(SB),NOSPLIT,$0
191         MOVL    mode+0(FP), DI          // arg 1 sig
192         MOVQ    new+8(FP), SI           // arg 2 act
193         MOVQ    old+16(FP), DX          // arg 3 oact
194         MOVQ    old+16(FP), CX          // arg 3 oact
195         MOVQ    old+16(FP), R10         // arg 3 oact
196         MOVL    $(0x2000000+46), AX     // syscall entry
197         SYSCALL
198         JCC     2(PC)
199         MOVL    $0xf1, 0xf1  // crash
200         RET
201
202 TEXT runtime·sigtramp(SB),NOSPLIT,$64
203         get_tls(BX)
204
205         MOVQ    R8, 32(SP)      // save ucontext
206         MOVQ    SI, 40(SP)      // save infostyle
207
208         // check that g exists
209         MOVQ    g(BX), R10
210         CMPQ    R10, $0
211         JNE     5(PC)
212         MOVL    DX, 0(SP)
213         MOVQ    $runtime·badsignal(SB), AX
214         CALL    AX
215         JMP     ret
216
217         // save g
218         MOVQ    R10, 48(SP)
219
220         // g = m->gsignal
221         MOVQ    g_m(R10), BP
222         MOVQ    m_gsignal(BP), BP
223         MOVQ    BP, g(BX)
224
225         MOVL    DX, 0(SP)
226         MOVQ    CX, 8(SP)
227         MOVQ    R8, 16(SP)
228         MOVQ    R10, 24(SP)
229
230         CALL    DI
231
232         // restore g
233         get_tls(BX)
234         MOVQ    48(SP), R10
235         MOVQ    R10, g(BX)
236
237 ret:
238         // call sigreturn
239         MOVL    $(0x2000000+184), AX    // sigreturn(ucontext, infostyle)
240         MOVQ    32(SP), DI      // saved ucontext
241         MOVQ    40(SP), SI      // saved infostyle
242         SYSCALL
243         INT $3  // not reached
244
245 TEXT runtime·mmap(SB),NOSPLIT,$0
246         MOVQ    addr+0(FP), DI          // arg 1 addr
247         MOVQ    n+8(FP), SI             // arg 2 len
248         MOVL    prot+16(FP), DX         // arg 3 prot
249         MOVL    flags+20(FP), R10               // arg 4 flags
250         MOVL    fd+24(FP), R8           // arg 5 fid
251         MOVL    off+28(FP), R9          // arg 6 offset
252         MOVL    $(0x2000000+197), AX    // syscall entry
253         SYSCALL
254         MOVQ    AX, ret+32(FP)
255         RET
256
257 TEXT runtime·munmap(SB),NOSPLIT,$0
258         MOVQ    addr+0(FP), DI          // arg 1 addr
259         MOVQ    n+8(FP), SI             // arg 2 len
260         MOVL    $(0x2000000+73), AX     // syscall entry
261         SYSCALL
262         JCC     2(PC)
263         MOVL    $0xf1, 0xf1  // crash
264         RET
265
266 TEXT runtime·sigaltstack(SB),NOSPLIT,$0
267         MOVQ    new+8(SP), DI
268         MOVQ    old+16(SP), SI
269         MOVQ    $(0x2000000+53), AX
270         SYSCALL
271         JCC     2(PC)
272         MOVL    $0xf1, 0xf1  // crash
273         RET
274
275 TEXT runtime·usleep(SB),NOSPLIT,$16
276         MOVL    $0, DX
277         MOVL    usec+0(FP), AX
278         MOVL    $1000000, CX
279         DIVL    CX
280         MOVQ    AX, 0(SP)  // sec
281         MOVL    DX, 8(SP)  // usec
282
283         // select(0, 0, 0, 0, &tv)
284         MOVL    $0, DI
285         MOVL    $0, SI
286         MOVL    $0, DX
287         MOVL    $0, R10
288         MOVQ    SP, R8
289         MOVL    $(0x2000000+93), AX
290         SYSCALL
291         RET
292
293 // void bsdthread_create(void *stk, M *mp, G *gp, void (*fn)(void))
294 TEXT runtime·bsdthread_create(SB),NOSPLIT,$0
295         // Set up arguments to bsdthread_create system call.
296         // The ones in quotes pass through to the thread callback
297         // uninterpreted, so we can put whatever we want there.
298         MOVQ    fn+32(SP), DI   // "func"
299         MOVQ    mm+16(SP), SI   // "arg"
300         MOVQ    stk+8(SP), DX   // stack
301         MOVQ    gg+24(SP), R10  // "pthread"
302         MOVQ    $0x01000000, R8 // flags = PTHREAD_START_CUSTOM
303         MOVQ    $0, R9  // paranoia
304         MOVQ    $(0x2000000+360), AX    // bsdthread_create
305         SYSCALL
306         JCC 4(PC)
307         NEGQ    AX
308         MOVL    AX, ret+32(FP)
309         RET
310         MOVL    $0, AX
311         MOVL    AX, ret+32(FP)
312         RET
313
314 // The thread that bsdthread_create creates starts executing here,
315 // because we registered this function using bsdthread_register
316 // at startup.
317 //      DI = "pthread"
318 //      SI = mach thread port
319 //      DX = "func" (= fn)
320 //      CX = "arg" (= m)
321 //      R8 = stack
322 //      R9 = flags (= 0)
323 //      SP = stack - C_64_REDZONE_LEN (= stack - 128)
324 TEXT runtime·bsdthread_start(SB),NOSPLIT,$0
325         MOVQ    R8, SP          // empirically, SP is very wrong but R8 is right
326
327         PUSHQ   DX
328         PUSHQ   CX
329         PUSHQ   SI
330
331         // set up thread local storage pointing at m->tls.
332         LEAQ    m_tls(CX), DI
333         CALL    runtime·settls(SB)
334
335         POPQ    SI
336         POPQ    CX
337         POPQ    DX
338
339         get_tls(BX)
340         MOVQ    SI, m_procid(CX)        // thread port is m->procid
341         MOVQ    m_g0(CX), AX
342         MOVQ    AX, g(BX)
343         MOVQ    CX, g_m(AX)
344         CALL    runtime·stackcheck(SB) // smashes AX, CX
345         CALL    DX      // fn
346         CALL    runtime·exit1(SB)
347         RET
348
349 // void bsdthread_register(void)
350 // registers callbacks for threadstart (see bsdthread_create above
351 // and wqthread and pthsize (not used).  returns 0 on success.
352 TEXT runtime·bsdthread_register(SB),NOSPLIT,$0
353         MOVQ    $runtime·bsdthread_start(SB), DI       // threadstart
354         MOVQ    $0, SI  // wqthread, not used by us
355         MOVQ    $0, DX  // pthsize, not used by us
356         MOVQ    $0, R10 // dummy_value [sic]
357         MOVQ    $0, R8  // targetconc_ptr
358         MOVQ    $0, R9  // dispatchqueue_offset
359         MOVQ    $(0x2000000+366), AX    // bsdthread_register
360         SYSCALL
361         JCC 4(PC)
362         NEGQ    AX
363         MOVL    AX, ret+0(FP)
364         RET
365         MOVL    $0, AX
366         MOVL    AX, ret+0(FP)
367         RET
368
369 // Mach system calls use 0x1000000 instead of the BSD's 0x2000000.
370
371 // uint32 mach_msg_trap(void*, uint32, uint32, uint32, uint32, uint32, uint32)
372 TEXT runtime·mach_msg_trap(SB),NOSPLIT,$0
373         MOVQ    h+0(FP), DI
374         MOVL    op+8(FP), SI
375         MOVL    send_size+12(FP), DX
376         MOVL    rcv_size+16(FP), R10
377         MOVL    rcv_name+20(FP), R8
378         MOVL    timeout+24(FP), R9
379         MOVL    notify+28(FP), R11
380         PUSHQ   R11     // seventh arg, on stack
381         MOVL    $(0x1000000+31), AX     // mach_msg_trap
382         SYSCALL
383         POPQ    R11
384         MOVL    AX, ret+32(FP)
385         RET
386
387 TEXT runtime·mach_task_self(SB),NOSPLIT,$0
388         MOVL    $(0x1000000+28), AX     // task_self_trap
389         SYSCALL
390         MOVL    AX, ret+0(FP)
391         RET
392
393 TEXT runtime·mach_thread_self(SB),NOSPLIT,$0
394         MOVL    $(0x1000000+27), AX     // thread_self_trap
395         SYSCALL
396         MOVL    AX, ret+0(FP)
397         RET
398
399 TEXT runtime·mach_reply_port(SB),NOSPLIT,$0
400         MOVL    $(0x1000000+26), AX     // mach_reply_port
401         SYSCALL
402         MOVL    AX, ret+0(FP)
403         RET
404
405 // Mach provides trap versions of the semaphore ops,
406 // instead of requiring the use of RPC.
407
408 // uint32 mach_semaphore_wait(uint32)
409 TEXT runtime·mach_semaphore_wait(SB),NOSPLIT,$0
410         MOVL    sema+0(FP), DI
411         MOVL    $(0x1000000+36), AX     // semaphore_wait_trap
412         SYSCALL
413         MOVL    AX, ret+8(FP)
414         RET
415
416 // uint32 mach_semaphore_timedwait(uint32, uint32, uint32)
417 TEXT runtime·mach_semaphore_timedwait(SB),NOSPLIT,$0
418         MOVL    sema+0(FP), DI
419         MOVL    sec+4(FP), SI
420         MOVL    nsec+8(FP), DX
421         MOVL    $(0x1000000+38), AX     // semaphore_timedwait_trap
422         SYSCALL
423         MOVL    AX, ret+16(FP)
424         RET
425
426 // uint32 mach_semaphore_signal(uint32)
427 TEXT runtime·mach_semaphore_signal(SB),NOSPLIT,$0
428         MOVL    sema+0(FP), DI
429         MOVL    $(0x1000000+33), AX     // semaphore_signal_trap
430         SYSCALL
431         MOVL    AX, ret+8(FP)
432         RET
433
434 // uint32 mach_semaphore_signal_all(uint32)
435 TEXT runtime·mach_semaphore_signal_all(SB),NOSPLIT,$0
436         MOVL    sema+0(FP), DI
437         MOVL    $(0x1000000+34), AX     // semaphore_signal_all_trap
438         SYSCALL
439         MOVL    AX, ret+8(FP)
440         RET
441
442 // set tls base to DI
443 TEXT runtime·settls(SB),NOSPLIT,$32
444         /*
445         * Same as in sys_darwin_386.s:/ugliness, different constant.
446         * See cgo/gcc_darwin_amd64.c for the derivation
447         * of the constant.
448         */
449         SUBQ $0x8a0, DI
450
451         MOVL    $(0x3000000+3), AX      // thread_fast_set_cthread_self - machdep call #3
452         SYSCALL
453         RET
454
455 TEXT runtime·sysctl(SB),NOSPLIT,$0
456         MOVQ    mib+0(FP), DI
457         MOVL    miblen+8(FP), SI
458         MOVQ    out+16(FP), DX
459         MOVQ    size+24(FP), R10
460         MOVQ    dst+32(FP), R8
461         MOVQ    ndst+40(FP), R9
462         MOVL    $(0x2000000+202), AX    // syscall entry
463         SYSCALL
464         JCC 4(PC)
465         NEGQ    AX
466         MOVL    AX, ret+48(FP)
467         RET
468         MOVL    $0, AX
469         MOVL    AX, ret+48(FP)
470         RET
471
472 // int32 runtime·kqueue(void);
473 TEXT runtime·kqueue(SB),NOSPLIT,$0
474         MOVQ    $0, DI
475         MOVQ    $0, SI
476         MOVQ    $0, DX
477         MOVL    $(0x2000000+362), AX
478         SYSCALL
479         JCC     2(PC)
480         NEGQ    AX
481         MOVL    AX, ret+0(FP)
482         RET
483
484 // int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout);
485 TEXT runtime·kevent(SB),NOSPLIT,$0
486         MOVL    fd+0(FP), DI
487         MOVQ    ev1+8(FP), SI
488         MOVL    nev1+16(FP), DX
489         MOVQ    ev2+24(FP), R10
490         MOVL    nev2+32(FP), R8
491         MOVQ    ts+40(FP), R9
492         MOVL    $(0x2000000+363), AX
493         SYSCALL
494         JCC     2(PC)
495         NEGQ    AX
496         MOVL    AX, ret+48(FP)
497         RET
498
499 // void runtime·closeonexec(int32 fd);
500 TEXT runtime·closeonexec(SB),NOSPLIT,$0
501         MOVL    fd+0(FP), DI  // fd
502         MOVQ    $2, SI  // F_SETFD
503         MOVQ    $1, DX  // FD_CLOEXEC
504         MOVL    $(0x2000000+92), AX  // fcntl
505         SYSCALL
506         RET