blob: e4315645fe04f70eba09e8e3e3d32d6f27fd735f [file] [log] [blame]
Aram Hăvărneanu50df1362014-02-24 22:31:01 -05001// Copyright 2014 The Go Authors. All rights reserved.
Aram Hăvărneanua46b4342014-01-17 17:58:10 +13002// 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 AMD64, SunOS
6// /usr/include/sys/syscall.h for syscall numbers.
7//
8
Russ Cox15ced2d2014-11-11 17:06:22 -05009#include "go_asm.h"
10#include "go_tls.h"
Russ Coxcb040d52014-09-04 23:05:18 -040011#include "textflag.h"
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130012
13// This is needed by asm_amd64.s
14TEXT runtime·settls(SB),NOSPLIT,$8
15 RET
16
Aram Hăvărneanue088e162014-11-13 16:07:10 +010017// void libc_miniterrno(void *(*___errno)(void));
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130018//
19// Set the TLS errno pointer in M.
20//
21// Called using runtime·asmcgocall from os_solaris.c:/minit.
Russ Cox997809c2014-08-27 14:52:25 -040022// NOT USING GO CALLING CONVENTION.
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130023TEXT runtime·miniterrno(SB),NOSPLIT,$0
24 // asmcgocall will put first argument into DI.
25 CALL DI // SysV ABI so returns in AX
26 get_tls(CX)
Russ Cox89f185f2014-06-26 11:54:39 -040027 MOVQ g(CX), BX
28 MOVQ g_m(BX), BX
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130029 MOVQ AX, m_perrno(BX)
30 RET
31
32// int64 runtime·nanotime1(void);
33//
34// clock_gettime(3c) wrapper because Timespec is too large for
35// runtime·nanotime stack.
36//
37// Called using runtime·sysvicall6 from os_solaris.c:/nanotime.
Russ Cox997809c2014-08-27 14:52:25 -040038// NOT USING GO CALLING CONVENTION.
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130039TEXT runtime·nanotime1(SB),NOSPLIT,$0
40 // need space for the timespec argument.
41 SUBQ $64, SP // 16 bytes will do, but who knows in the future?
42 MOVQ $3, DI // CLOCK_REALTIME from <sys/time_impl.h>
43 MOVQ SP, SI
Aram Hăvărneanuc94f1f72015-03-30 13:52:07 +020044 LEAQ libc_clock_gettime(SB), AX
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130045 CALL AX
46 MOVQ (SP), AX // tv_sec from struct timespec
47 IMULQ $1000000000, AX // multiply into nanoseconds
48 ADDQ 8(SP), AX // tv_nsec, offset should be stable.
49 ADDQ $64, SP
50 RET
51
52// pipe(3c) wrapper that returns fds in AX, DX.
Russ Cox997809c2014-08-27 14:52:25 -040053// NOT USING GO CALLING CONVENTION.
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130054TEXT runtime·pipe1(SB),NOSPLIT,$0
55 SUBQ $16, SP // 8 bytes will do, but stack has to be 16-byte alligned
56 MOVQ SP, DI
Aram Hăvărneanuc94f1f72015-03-30 13:52:07 +020057 LEAQ libc_pipe(SB), AX
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130058 CALL AX
59 MOVL 0(SP), AX
60 MOVL 4(SP), DX
61 ADDQ $16, SP
62 RET
63
64// Call a library function with SysV calling conventions.
65// The called function can take a maximum of 6 INTEGER class arguments,
66// see
67// Michael Matz, Jan Hubicka, Andreas Jaeger, and Mark Mitchell
68// System V Application Binary Interface
69// AMD64 Architecture Processor Supplement
70// section 3.2.3.
71//
72// Called by runtime·asmcgocall or runtime·cgocall.
Russ Cox997809c2014-08-27 14:52:25 -040073// NOT USING GO CALLING CONVENTION.
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130074TEXT runtime·asmsysvicall6(SB),NOSPLIT,$0
75 // asmcgocall will put first argument into DI.
76 PUSHQ DI // save for later
77 MOVQ libcall_fn(DI), AX
78 MOVQ libcall_args(DI), R11
79 MOVQ libcall_n(DI), R10
80
81 get_tls(CX)
Russ Cox89f185f2014-06-26 11:54:39 -040082 MOVQ g(CX), BX
83 MOVQ g_m(BX), BX
Aram Hăvărneanua46b4342014-01-17 17:58:10 +130084 MOVQ m_perrno(BX), DX
85 CMPQ DX, $0
86 JEQ skiperrno1
87 MOVL $0, 0(DX)
88
89skiperrno1:
90 CMPQ R11, $0
91 JEQ skipargs
92 // Load 6 args into correspondent registers.
93 MOVQ 0(R11), DI
94 MOVQ 8(R11), SI
95 MOVQ 16(R11), DX
96 MOVQ 24(R11), CX
97 MOVQ 32(R11), R8
98 MOVQ 40(R11), R9
99skipargs:
100
101 // Call SysV function
102 CALL AX
103
104 // Return result
105 POPQ DI
106 MOVQ AX, libcall_r1(DI)
107 MOVQ DX, libcall_r2(DI)
108
109 get_tls(CX)
Russ Cox89f185f2014-06-26 11:54:39 -0400110 MOVQ g(CX), BX
111 MOVQ g_m(BX), BX
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300112 MOVQ m_perrno(BX), AX
113 CMPQ AX, $0
114 JEQ skiperrno2
115 MOVL 0(AX), AX
116 MOVQ AX, libcall_err(DI)
117
118skiperrno2:
119 RET
120
121// uint32 tstart_sysvicall(M *newm);
122TEXT runtime·tstart_sysvicall(SB),NOSPLIT,$0
123 // DI contains first arg newm
124 MOVQ m_g0(DI), DX // g
125
126 // Make TLS entries point at g and m.
127 get_tls(BX)
128 MOVQ DX, g(BX)
Russ Cox89f185f2014-06-26 11:54:39 -0400129 MOVQ DI, g_m(DX)
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300130
131 // Layout new m scheduler stack on os stack.
132 MOVQ SP, AX
Russ Cox8ac35be2014-09-09 14:02:37 -0400133 MOVQ AX, (g_stack+stack_hi)(DX)
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300134 SUBQ $(0x100000), AX // stack size
Russ Cox8ac35be2014-09-09 14:02:37 -0400135 MOVQ AX, (g_stack+stack_lo)(DX)
Aram Hăvărneanue088e162014-11-13 16:07:10 +0100136 ADDQ $const__StackGuard, AX
Russ Coxe6d35112015-01-05 16:29:21 +0000137 MOVQ AX, g_stackguard0(DX)
138 MOVQ AX, g_stackguard1(DX)
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300139
140 // Someday the convention will be D is always cleared.
141 CLD
142
143 CALL runtime·stackcheck(SB) // clobbers AX,CX
144 CALL runtime·mstart(SB)
145
146 XORL AX, AX // return 0 == success
Russ Cox25f6b022014-08-27 11:32:17 -0400147 MOVL AX, ret+8(FP)
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300148 RET
149
150// Careful, this is called by __sighndlr, a libc function. We must preserve
151// registers as per AMD 64 ABI.
152TEXT runtime·sigtramp(SB),NOSPLIT,$0
153 // Note that we are executing on altsigstack here, so we have
154 // more stack available than NOSPLIT would have us believe.
155 // To defeat the linker, we make our own stack frame with
156 // more space:
157 SUBQ $184, SP
158
159 // save registers
160 MOVQ BX, 32(SP)
161 MOVQ BP, 40(SP)
162 MOVQ R12, 48(SP)
163 MOVQ R13, 56(SP)
164 MOVQ R14, 64(SP)
165 MOVQ R15, 72(SP)
166
167 get_tls(BX)
Russ Cox89f185f2014-06-26 11:54:39 -0400168 // check that g exists
169 MOVQ g(BX), R10
170 CMPQ R10, $0
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300171 JNE allgood
172 MOVQ DI, 0(SP)
173 MOVQ $runtime·badsignal(SB), AX
174 CALL AX
Aram Hăvărneanud7b678b2014-07-02 09:34:06 +1000175 JMP exit
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300176
177allgood:
178 // save g
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300179 MOVQ R10, 80(SP)
180
181 // Save m->libcall and m->scratch. We need to do this because we
182 // might get interrupted by a signal in runtime·asmcgocall.
183
184 // save m->libcall
Russ Cox89f185f2014-06-26 11:54:39 -0400185 MOVQ g_m(R10), BP
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300186 LEAQ m_libcall(BP), R11
187 MOVQ libcall_fn(R11), R10
188 MOVQ R10, 88(SP)
189 MOVQ libcall_args(R11), R10
190 MOVQ R10, 96(SP)
191 MOVQ libcall_n(R11), R10
192 MOVQ R10, 104(SP)
193 MOVQ libcall_r1(R11), R10
194 MOVQ R10, 168(SP)
195 MOVQ libcall_r2(R11), R10
196 MOVQ R10, 176(SP)
197
198 // save m->scratch
199 LEAQ m_scratch(BP), R11
200 MOVQ 0(R11), R10
201 MOVQ R10, 112(SP)
202 MOVQ 8(R11), R10
203 MOVQ R10, 120(SP)
204 MOVQ 16(R11), R10
205 MOVQ R10, 128(SP)
206 MOVQ 24(R11), R10
207 MOVQ R10, 136(SP)
208 MOVQ 32(R11), R10
209 MOVQ R10, 144(SP)
210 MOVQ 40(R11), R10
211 MOVQ R10, 152(SP)
212
213 // save errno, it might be EINTR; stuff we do here might reset it.
214 MOVQ m_perrno(BP), R10
215 MOVL 0(R10), R10
216 MOVQ R10, 160(SP)
217
218 MOVQ g(BX), R10
219 // g = m->gsignal
220 MOVQ m_gsignal(BP), BP
221 MOVQ BP, g(BX)
222
223 // prepare call
224 MOVQ DI, 0(SP)
225 MOVQ SI, 8(SP)
226 MOVQ DX, 16(SP)
227 MOVQ R10, 24(SP)
228 CALL runtime·sighandler(SB)
229
230 get_tls(BX)
Russ Cox89f185f2014-06-26 11:54:39 -0400231 MOVQ g(BX), BP
232 MOVQ g_m(BP), BP
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300233 // restore libcall
234 LEAQ m_libcall(BP), R11
235 MOVQ 88(SP), R10
236 MOVQ R10, libcall_fn(R11)
237 MOVQ 96(SP), R10
238 MOVQ R10, libcall_args(R11)
239 MOVQ 104(SP), R10
240 MOVQ R10, libcall_n(R11)
241 MOVQ 168(SP), R10
242 MOVQ R10, libcall_r1(R11)
243 MOVQ 176(SP), R10
244 MOVQ R10, libcall_r2(R11)
245
246 // restore scratch
247 LEAQ m_scratch(BP), R11
248 MOVQ 112(SP), R10
249 MOVQ R10, 0(R11)
250 MOVQ 120(SP), R10
251 MOVQ R10, 8(R11)
252 MOVQ 128(SP), R10
253 MOVQ R10, 16(R11)
254 MOVQ 136(SP), R10
255 MOVQ R10, 24(R11)
256 MOVQ 144(SP), R10
257 MOVQ R10, 32(R11)
258 MOVQ 152(SP), R10
259 MOVQ R10, 40(R11)
260
261 // restore errno
262 MOVQ m_perrno(BP), R11
263 MOVQ 160(SP), R10
264 MOVL R10, 0(R11)
265
266 // restore g
267 MOVQ 80(SP), R10
268 MOVQ R10, g(BX)
269
Aram Hăvărneanud7b678b2014-07-02 09:34:06 +1000270exit:
Aram Hăvărneanua46b4342014-01-17 17:58:10 +1300271 // restore registers
272 MOVQ 32(SP), BX
273 MOVQ 40(SP), BP
274 MOVQ 48(SP), R12
275 MOVQ 56(SP), R13
276 MOVQ 64(SP), R14
277 MOVQ 72(SP), R15
278
279 ADDQ $184, SP
280 RET
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000281
282// Called from runtime·usleep (Go). Can be called on Go stack, on OS stack,
283// can also be called in cgo callback path without a g->m.
284TEXT runtime·usleep1(SB),NOSPLIT,$0
Russ Cox25f6b022014-08-27 11:32:17 -0400285 MOVL usec+0(FP), DI
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000286 MOVQ $runtime·usleep2(SB), AX // to hide from 6l
287
288 // Execute call on m->g0.
289 get_tls(R15)
290 CMPQ R15, $0
Russ Coxb55791e2014-10-28 21:50:16 -0400291 JE noswitch
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000292
293 MOVQ g(R15), R13
294 CMPQ R13, $0
Russ Coxb55791e2014-10-28 21:50:16 -0400295 JE noswitch
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000296 MOVQ g_m(R13), R13
297 CMPQ R13, $0
Russ Coxb55791e2014-10-28 21:50:16 -0400298 JE noswitch
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000299 // TODO(aram): do something about the cpu profiler here.
300
301 MOVQ m_g0(R13), R14
302 CMPQ g(R15), R14
Russ Coxb55791e2014-10-28 21:50:16 -0400303 JNE switch
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000304 // executing on m->g0 already
305 CALL AX
306 RET
307
Russ Coxb55791e2014-10-28 21:50:16 -0400308switch:
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000309 // Switch to m->g0 stack and back.
310 MOVQ (g_sched+gobuf_sp)(R14), R14
311 MOVQ SP, -8(R14)
312 LEAQ -8(R14), SP
313 CALL AX
314 MOVQ 0(SP), SP
315 RET
316
Russ Coxb55791e2014-10-28 21:50:16 -0400317noswitch:
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000318 // Not a Go-managed thread. Do not switch stack.
319 CALL AX
320 RET
321
322// Runs on OS stack. duration (in µs units) is in DI.
323TEXT runtime·usleep2(SB),NOSPLIT,$0
Aram Hăvărneanuc94f1f72015-03-30 13:52:07 +0200324 LEAQ libc_usleep(SB), AX
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000325 CALL AX
326 RET
327
328// Runs on OS stack, called from runtime·osyield.
329TEXT runtime·osyield1(SB),NOSPLIT,$0
Aram Hăvărneanuc94f1f72015-03-30 13:52:07 +0200330 LEAQ libc_sched_yield(SB), AX
Aram Hăvărneanudf75f082014-07-03 11:36:05 +1000331 CALL AX
332 RET
Russ Cox13d0b822014-09-07 23:40:59 -0400333
334// func now() (sec int64, nsec int32)
335TEXT time·now(SB),NOSPLIT,$8-12
336 CALL runtime·nanotime(SB)
337 MOVQ 0(SP), AX
338
339 // generated code for
340 // func f(x uint64) (uint64, uint64) { return x/1000000000, x%100000000 }
341 // adapted to reduce duplication
342 MOVQ AX, CX
343 MOVQ $1360296554856532783, AX
344 MULQ CX
345 ADDQ CX, DX
346 RCRQ $1, DX
347 SHRQ $29, DX
348 MOVQ DX, sec+0(FP)
349 IMULQ $1000000000, DX
350 SUBQ DX, CX
351 MOVL CX, nsec+8(FP)
352 RET