Text file
src/runtime/sys_openbsd_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 // System calls and other sys.stuff for AMD64, OpenBSD.
6 // System calls are implemented in libc/libpthread, this file
7 // contains trampolines that convert from Go to C calling convention.
8 // Some direct system call implementations currently remain.
9 //
10
11 #include "go_asm.h"
12 #include "go_tls.h"
13 #include "textflag.h"
14 #include "cgo/abi_amd64.h"
15
16 #define CLOCK_MONOTONIC $3
17
18 TEXT runtime·settls(SB),NOSPLIT,$0
19 // Nothing to do, pthread already set thread-local storage up.
20 RET
21
22 // mstart_stub is the first function executed on a new thread started by pthread_create.
23 // It just does some low-level setup and then calls mstart.
24 // Note: called with the C calling convention.
25 TEXT runtime·mstart_stub(SB),NOSPLIT,$0
26 // DI points to the m.
27 // We are already on m's g0 stack.
28
29 // Transition from C ABI to Go ABI.
30 PUSH_REGS_HOST_TO_ABI0()
31
32 // Load g and save to TLS entry.
33 // See cmd/link/internal/ld/sym.go:computeTLSOffset.
34 MOVQ m_g0(DI), DX // g
35 MOVQ DX, -8(FS)
36
37 CALL runtime·mstart(SB)
38
39 POP_REGS_HOST_TO_ABI0()
40
41 // Go is all done with this OS thread.
42 // Tell pthread everything is ok (we never join with this thread, so
43 // the value here doesn't really matter).
44 XORL AX, AX
45 RET
46
47 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
48 MOVQ fn+0(FP), AX
49 MOVL sig+8(FP), DI
50 MOVQ info+16(FP), SI
51 MOVQ ctx+24(FP), DX
52 PUSHQ BP
53 MOVQ SP, BP
54 ANDQ $~15, SP // alignment for x86_64 ABI
55 CALL AX
56 MOVQ BP, SP
57 POPQ BP
58 RET
59
60 // Called using C ABI.
61 TEXT runtime·sigtramp(SB),NOSPLIT,$0
62 // Transition from C ABI to Go ABI.
63 PUSH_REGS_HOST_TO_ABI0()
64
65 // Call into the Go signal handler
66 NOP SP // disable vet stack checking
67 ADJSP $24
68 MOVQ DI, 0(SP) // sig
69 MOVQ SI, 8(SP) // info
70 MOVQ DX, 16(SP) // ctx
71 CALL ·sigtrampgo(SB)
72 ADJSP $-24
73
74 POP_REGS_HOST_TO_ABI0()
75 RET
76
77 //
78 // These trampolines help convert from Go calling convention to C calling convention.
79 // They should be called with asmcgocall.
80 // A pointer to the arguments is passed in DI.
81 // A single int32 result is returned in AX.
82 // (For more results, make an args/results structure.)
83 TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
84 PUSHQ BP
85 MOVQ SP, BP
86 MOVQ 0(DI), DI // arg 1 - attr
87 CALL libc_pthread_attr_init(SB)
88 POPQ BP
89 RET
90
91 TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0
92 PUSHQ BP
93 MOVQ SP, BP
94 MOVQ 0(DI), DI // arg 1 - attr
95 CALL libc_pthread_attr_destroy(SB)
96 POPQ BP
97 RET
98
99 TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
100 PUSHQ BP
101 MOVQ SP, BP
102 MOVQ 8(DI), SI // arg 2 - stacksize
103 MOVQ 0(DI), DI // arg 1 - attr
104 CALL libc_pthread_attr_getstacksize(SB)
105 POPQ BP
106 RET
107
108 TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
109 PUSHQ BP
110 MOVQ SP, BP
111 MOVQ 8(DI), SI // arg 2 - detachstate
112 MOVQ 0(DI), DI // arg 1 - attr
113 CALL libc_pthread_attr_setdetachstate(SB)
114 POPQ BP
115 RET
116
117 TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
118 PUSHQ BP
119 MOVQ SP, BP
120 SUBQ $16, SP
121 MOVQ 0(DI), SI // arg 2 - attr
122 MOVQ 8(DI), DX // arg 3 - start
123 MOVQ 16(DI), CX // arg 4 - arg
124 MOVQ SP, DI // arg 1 - &thread (discarded)
125 CALL libc_pthread_create(SB)
126 MOVQ BP, SP
127 POPQ BP
128 RET
129
130 TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
131 PUSHQ BP
132 MOVQ SP, BP
133 MOVL 8(DI), SI // arg 2 - signal
134 MOVQ $0, DX // arg 3 - tcb
135 MOVL 0(DI), DI // arg 1 - tid
136 CALL libc_thrkill(SB)
137 POPQ BP
138 RET
139
140 TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
141 PUSHQ BP
142 MOVQ SP, BP
143 MOVL 8(DI), SI // arg 2 - clock_id
144 MOVQ 16(DI), DX // arg 3 - abstime
145 MOVQ 24(DI), CX // arg 4 - lock
146 MOVQ 32(DI), R8 // arg 5 - abort
147 MOVQ 0(DI), DI // arg 1 - id
148 CALL libc_thrsleep(SB)
149 POPQ BP
150 RET
151
152 TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
153 PUSHQ BP
154 MOVQ SP, BP
155 MOVL 8(DI), SI // arg 2 - count
156 MOVQ 0(DI), DI // arg 1 - id
157 CALL libc_thrwakeup(SB)
158 POPQ BP
159 RET
160
161 TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
162 PUSHQ BP
163 MOVQ SP, BP
164 MOVL 0(DI), DI // arg 1 exit status
165 CALL libc_exit(SB)
166 MOVL $0xf1, 0xf1 // crash
167 POPQ BP
168 RET
169
170 TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
171 PUSHQ BP
172 MOVQ SP, BP
173 MOVQ DI, BX // BX is caller-save
174 CALL libc_getthrid(SB)
175 MOVL AX, 0(BX) // return value
176 POPQ BP
177 RET
178
179 TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
180 PUSHQ BP
181 MOVQ SP, BP
182 MOVL 0(DI), BX // signal
183 CALL libc_getpid(SB)
184 MOVL AX, DI // arg 1 pid
185 MOVL BX, SI // arg 2 signal
186 CALL libc_kill(SB)
187 POPQ BP
188 RET
189
190 TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
191 PUSHQ BP
192 MOVQ SP, BP
193 CALL libc_sched_yield(SB)
194 POPQ BP
195 RET
196
197 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
198 PUSHQ BP // make a frame; keep stack aligned
199 MOVQ SP, BP
200 MOVQ DI, BX
201 MOVQ 0(BX), DI // arg 1 addr
202 MOVQ 8(BX), SI // arg 2 len
203 MOVL 16(BX), DX // arg 3 prot
204 MOVL 20(BX), CX // arg 4 flags
205 MOVL 24(BX), R8 // arg 5 fid
206 MOVL 28(BX), R9 // arg 6 offset
207 CALL libc_mmap(SB)
208 XORL DX, DX
209 CMPQ AX, $-1
210 JNE ok
211 CALL libc_errno(SB)
212 MOVLQSX (AX), DX // errno
213 XORQ AX, AX
214 ok:
215 MOVQ AX, 32(BX)
216 MOVQ DX, 40(BX)
217 POPQ BP
218 RET
219
220 TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
221 PUSHQ BP
222 MOVQ SP, BP
223 MOVQ 8(DI), SI // arg 2 len
224 MOVQ 0(DI), DI // arg 1 addr
225 CALL libc_munmap(SB)
226 TESTQ AX, AX
227 JEQ 2(PC)
228 MOVL $0xf1, 0xf1 // crash
229 POPQ BP
230 RET
231
232 TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
233 PUSHQ BP
234 MOVQ SP, BP
235 MOVQ 8(DI), SI // arg 2 len
236 MOVL 16(DI), DX // arg 3 advice
237 MOVQ 0(DI), DI // arg 1 addr
238 CALL libc_madvise(SB)
239 // ignore failure - maybe pages are locked
240 POPQ BP
241 RET
242
243 TEXT runtime·open_trampoline(SB),NOSPLIT,$0
244 PUSHQ BP
245 MOVQ SP, BP
246 MOVL 8(DI), SI // arg 2 - flags
247 MOVL 12(DI), DX // arg 3 - mode
248 MOVQ 0(DI), DI // arg 1 - path
249 XORL AX, AX // vararg: say "no float args"
250 CALL libc_open(SB)
251 POPQ BP
252 RET
253
254 TEXT runtime·close_trampoline(SB),NOSPLIT,$0
255 PUSHQ BP
256 MOVQ SP, BP
257 MOVL 0(DI), DI // arg 1 - fd
258 CALL libc_close(SB)
259 POPQ BP
260 RET
261
262 TEXT runtime·read_trampoline(SB),NOSPLIT,$0
263 PUSHQ BP
264 MOVQ SP, BP
265 MOVQ 8(DI), SI // arg 2 - buf
266 MOVL 16(DI), DX // arg 3 - count
267 MOVL 0(DI), DI // arg 1 - fd
268 CALL libc_read(SB)
269 TESTL AX, AX
270 JGE noerr
271 CALL libc_errno(SB)
272 MOVL (AX), AX // errno
273 NEGL AX // caller expects negative errno value
274 noerr:
275 POPQ BP
276 RET
277
278 TEXT runtime·write_trampoline(SB),NOSPLIT,$0
279 PUSHQ BP
280 MOVQ SP, BP
281 MOVQ 8(DI), SI // arg 2 buf
282 MOVL 16(DI), DX // arg 3 count
283 MOVL 0(DI), DI // arg 1 fd
284 CALL libc_write(SB)
285 TESTL AX, AX
286 JGE noerr
287 CALL libc_errno(SB)
288 MOVL (AX), AX // errno
289 NEGL AX // caller expects negative errno value
290 noerr:
291 POPQ BP
292 RET
293
294 TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
295 PUSHQ BP
296 MOVQ SP, BP
297 MOVL 8(DI), SI // arg 2 flags
298 MOVQ 0(DI), DI // arg 1 filedes
299 CALL libc_pipe2(SB)
300 TESTL AX, AX
301 JEQ 3(PC)
302 CALL libc_errno(SB)
303 MOVL (AX), AX // errno
304 NEGL AX // caller expects negative errno value
305 POPQ BP
306 RET
307
308 TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
309 PUSHQ BP
310 MOVQ SP, BP
311 MOVQ 8(DI), SI // arg 2 new
312 MOVQ 16(DI), DX // arg 3 old
313 MOVL 0(DI), DI // arg 1 which
314 CALL libc_setitimer(SB)
315 POPQ BP
316 RET
317
318 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
319 PUSHQ BP
320 MOVQ SP, BP
321 MOVL 0(DI), DI // arg 1 usec
322 CALL libc_usleep(SB)
323 POPQ BP
324 RET
325
326 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
327 PUSHQ BP
328 MOVQ SP, BP
329 MOVL 8(DI), SI // arg 2 miblen
330 MOVQ 16(DI), DX // arg 3 out
331 MOVQ 24(DI), CX // arg 4 size
332 MOVQ 32(DI), R8 // arg 5 dst
333 MOVQ 40(DI), R9 // arg 6 ndst
334 MOVQ 0(DI), DI // arg 1 mib
335 CALL libc_sysctl(SB)
336 POPQ BP
337 RET
338
339 TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
340 PUSHQ BP
341 MOVQ SP, BP
342 CALL libc_kqueue(SB)
343 POPQ BP
344 RET
345
346 TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
347 PUSHQ BP
348 MOVQ SP, BP
349 MOVQ 8(DI), SI // arg 2 keventt
350 MOVL 16(DI), DX // arg 3 nch
351 MOVQ 24(DI), CX // arg 4 ev
352 MOVL 32(DI), R8 // arg 5 nev
353 MOVQ 40(DI), R9 // arg 6 ts
354 MOVL 0(DI), DI // arg 1 kq
355 CALL libc_kevent(SB)
356 CMPL AX, $-1
357 JNE ok
358 CALL libc_errno(SB)
359 MOVL (AX), AX // errno
360 NEGL AX // caller expects negative errno value
361 ok:
362 POPQ BP
363 RET
364
365 TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
366 PUSHQ BP // make a frame; keep stack aligned
367 MOVQ SP, BP
368 MOVQ 8(DI), SI // arg 2 tp
369 MOVL 0(DI), DI // arg 1 clock_id
370 CALL libc_clock_gettime(SB)
371 TESTL AX, AX
372 JEQ noerr
373 CALL libc_errno(SB)
374 MOVL (AX), AX // errno
375 NEGL AX // caller expects negative errno value
376 noerr:
377 POPQ BP
378 RET
379
380 TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
381 PUSHQ BP
382 MOVQ SP, BP
383 MOVL 4(DI), SI // arg 2 cmd
384 MOVL 8(DI), DX // arg 3 arg
385 MOVL 0(DI), DI // arg 1 fd
386 XORL AX, AX // vararg: say "no float args"
387 CALL libc_fcntl(SB)
388 POPQ BP
389 RET
390
391 TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
392 PUSHQ BP
393 MOVQ SP, BP
394 MOVQ 8(DI), SI // arg 2 new
395 MOVQ 16(DI), DX // arg 3 old
396 MOVL 0(DI), DI // arg 1 sig
397 CALL libc_sigaction(SB)
398 TESTL AX, AX
399 JEQ 2(PC)
400 MOVL $0xf1, 0xf1 // crash
401 POPQ BP
402 RET
403
404 TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
405 PUSHQ BP
406 MOVQ SP, BP
407 MOVQ 8(DI), SI // arg 2 new
408 MOVQ 16(DI), DX // arg 3 old
409 MOVL 0(DI), DI // arg 1 how
410 CALL libc_pthread_sigmask(SB)
411 TESTL AX, AX
412 JEQ 2(PC)
413 MOVL $0xf1, 0xf1 // crash
414 POPQ BP
415 RET
416
417 TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
418 PUSHQ BP
419 MOVQ SP, BP
420 MOVQ 8(DI), SI // arg 2 old
421 MOVQ 0(DI), DI // arg 1 new
422 CALL libc_sigaltstack(SB)
423 TESTQ AX, AX
424 JEQ 2(PC)
425 MOVL $0xf1, 0xf1 // crash
426 POPQ BP
427 RET
428
429 // syscall calls a function in libc on behalf of the syscall package.
430 // syscall takes a pointer to a struct like:
431 // struct {
432 // fn uintptr
433 // a1 uintptr
434 // a2 uintptr
435 // a3 uintptr
436 // r1 uintptr
437 // r2 uintptr
438 // err uintptr
439 // }
440 // syscall must be called on the g0 stack with the
441 // C calling convention (use libcCall).
442 //
443 // syscall expects a 32-bit result and tests for 32-bit -1
444 // to decide there was an error.
445 TEXT runtime·syscall(SB),NOSPLIT,$0
446 PUSHQ BP
447 MOVQ SP, BP
448 SUBQ $16, SP
449 MOVQ (0*8)(DI), CX // fn
450 MOVQ (2*8)(DI), SI // a2
451 MOVQ (3*8)(DI), DX // a3
452 MOVQ DI, (SP)
453 MOVQ (1*8)(DI), DI // a1
454 XORL AX, AX // vararg: say "no float args"
455
456 CALL CX
457
458 MOVQ (SP), DI
459 MOVQ AX, (4*8)(DI) // r1
460 MOVQ DX, (5*8)(DI) // r2
461
462 // Standard libc functions return -1 on error
463 // and set errno.
464 CMPL AX, $-1 // Note: high 32 bits are junk
465 JNE ok
466
467 // Get error code from libc.
468 CALL libc_errno(SB)
469 MOVLQSX (AX), AX
470 MOVQ (SP), DI
471 MOVQ AX, (6*8)(DI) // err
472
473 ok:
474 XORL AX, AX // no error (it's ignored anyway)
475 MOVQ BP, SP
476 POPQ BP
477 RET
478
479 // syscallX calls a function in libc on behalf of the syscall package.
480 // syscallX takes a pointer to a struct like:
481 // struct {
482 // fn uintptr
483 // a1 uintptr
484 // a2 uintptr
485 // a3 uintptr
486 // r1 uintptr
487 // r2 uintptr
488 // err uintptr
489 // }
490 // syscallX must be called on the g0 stack with the
491 // C calling convention (use libcCall).
492 //
493 // syscallX is like syscall but expects a 64-bit result
494 // and tests for 64-bit -1 to decide there was an error.
495 TEXT runtime·syscallX(SB),NOSPLIT,$0
496 PUSHQ BP
497 MOVQ SP, BP
498 SUBQ $16, SP
499 MOVQ (0*8)(DI), CX // fn
500 MOVQ (2*8)(DI), SI // a2
501 MOVQ (3*8)(DI), DX // a3
502 MOVQ DI, (SP)
503 MOVQ (1*8)(DI), DI // a1
504 XORL AX, AX // vararg: say "no float args"
505
506 CALL CX
507
508 MOVQ (SP), DI
509 MOVQ AX, (4*8)(DI) // r1
510 MOVQ DX, (5*8)(DI) // r2
511
512 // Standard libc functions return -1 on error
513 // and set errno.
514 CMPQ AX, $-1
515 JNE ok
516
517 // Get error code from libc.
518 CALL libc_errno(SB)
519 MOVLQSX (AX), AX
520 MOVQ (SP), DI
521 MOVQ AX, (6*8)(DI) // err
522
523 ok:
524 XORL AX, AX // no error (it's ignored anyway)
525 MOVQ BP, SP
526 POPQ BP
527 RET
528
529 // syscall6 calls a function in libc on behalf of the syscall package.
530 // syscall6 takes a pointer to a struct like:
531 // struct {
532 // fn uintptr
533 // a1 uintptr
534 // a2 uintptr
535 // a3 uintptr
536 // a4 uintptr
537 // a5 uintptr
538 // a6 uintptr
539 // r1 uintptr
540 // r2 uintptr
541 // err uintptr
542 // }
543 // syscall6 must be called on the g0 stack with the
544 // C calling convention (use libcCall).
545 //
546 // syscall6 expects a 32-bit result and tests for 32-bit -1
547 // to decide there was an error.
548 TEXT runtime·syscall6(SB),NOSPLIT,$0
549 PUSHQ BP
550 MOVQ SP, BP
551 SUBQ $16, SP
552 MOVQ (0*8)(DI), R11// fn
553 MOVQ (2*8)(DI), SI // a2
554 MOVQ (3*8)(DI), DX // a3
555 MOVQ (4*8)(DI), CX // a4
556 MOVQ (5*8)(DI), R8 // a5
557 MOVQ (6*8)(DI), R9 // a6
558 MOVQ DI, (SP)
559 MOVQ (1*8)(DI), DI // a1
560 XORL AX, AX // vararg: say "no float args"
561
562 CALL R11
563
564 MOVQ (SP), DI
565 MOVQ AX, (7*8)(DI) // r1
566 MOVQ DX, (8*8)(DI) // r2
567
568 CMPL AX, $-1
569 JNE ok
570
571 CALL libc_errno(SB)
572 MOVLQSX (AX), AX
573 MOVQ (SP), DI
574 MOVQ AX, (9*8)(DI) // err
575
576 ok:
577 XORL AX, AX // no error (it's ignored anyway)
578 MOVQ BP, SP
579 POPQ BP
580 RET
581
582 // syscall6X calls a function in libc on behalf of the syscall package.
583 // syscall6X takes a pointer to a struct like:
584 // struct {
585 // fn uintptr
586 // a1 uintptr
587 // a2 uintptr
588 // a3 uintptr
589 // a4 uintptr
590 // a5 uintptr
591 // a6 uintptr
592 // r1 uintptr
593 // r2 uintptr
594 // err uintptr
595 // }
596 // syscall6X must be called on the g0 stack with the
597 // C calling convention (use libcCall).
598 //
599 // syscall6X is like syscall6 but expects a 64-bit result
600 // and tests for 64-bit -1 to decide there was an error.
601 TEXT runtime·syscall6X(SB),NOSPLIT,$0
602 PUSHQ BP
603 MOVQ SP, BP
604 SUBQ $16, SP
605 MOVQ (0*8)(DI), R11// fn
606 MOVQ (2*8)(DI), SI // a2
607 MOVQ (3*8)(DI), DX // a3
608 MOVQ (4*8)(DI), CX // a4
609 MOVQ (5*8)(DI), R8 // a5
610 MOVQ (6*8)(DI), R9 // a6
611 MOVQ DI, (SP)
612 MOVQ (1*8)(DI), DI // a1
613 XORL AX, AX // vararg: say "no float args"
614
615 CALL R11
616
617 MOVQ (SP), DI
618 MOVQ AX, (7*8)(DI) // r1
619 MOVQ DX, (8*8)(DI) // r2
620
621 CMPQ AX, $-1
622 JNE ok
623
624 CALL libc_errno(SB)
625 MOVLQSX (AX), AX
626 MOVQ (SP), DI
627 MOVQ AX, (9*8)(DI) // err
628
629 ok:
630 XORL AX, AX // no error (it's ignored anyway)
631 MOVQ BP, SP
632 POPQ BP
633 RET
634
635 // syscall10 calls a function in libc on behalf of the syscall package.
636 // syscall10 takes a pointer to a struct like:
637 // struct {
638 // fn uintptr
639 // a1 uintptr
640 // a2 uintptr
641 // a3 uintptr
642 // a4 uintptr
643 // a5 uintptr
644 // a6 uintptr
645 // a7 uintptr
646 // a8 uintptr
647 // a9 uintptr
648 // a10 uintptr
649 // r1 uintptr
650 // r2 uintptr
651 // err uintptr
652 // }
653 // syscall10 must be called on the g0 stack with the
654 // C calling convention (use libcCall).
655 TEXT runtime·syscall10(SB),NOSPLIT,$0
656 PUSHQ BP
657 MOVQ SP, BP
658 SUBQ $48, SP
659
660 // Arguments a1 to a6 get passed in registers, with a7 onwards being
661 // passed via the stack per the x86-64 System V ABI
662 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
663 MOVQ (7*8)(DI), R10 // a7
664 MOVQ (8*8)(DI), R11 // a8
665 MOVQ (9*8)(DI), R12 // a9
666 MOVQ (10*8)(DI), R13 // a10
667 MOVQ R10, (0*8)(SP) // a7
668 MOVQ R11, (1*8)(SP) // a8
669 MOVQ R12, (2*8)(SP) // a9
670 MOVQ R13, (3*8)(SP) // a10
671 MOVQ (0*8)(DI), R11 // fn
672 MOVQ (2*8)(DI), SI // a2
673 MOVQ (3*8)(DI), DX // a3
674 MOVQ (4*8)(DI), CX // a4
675 MOVQ (5*8)(DI), R8 // a5
676 MOVQ (6*8)(DI), R9 // a6
677 MOVQ DI, (4*8)(SP)
678 MOVQ (1*8)(DI), DI // a1
679 XORL AX, AX // vararg: say "no float args"
680
681 CALL R11
682
683 MOVQ (4*8)(SP), DI
684 MOVQ AX, (11*8)(DI) // r1
685 MOVQ DX, (12*8)(DI) // r2
686
687 CMPL AX, $-1
688 JNE ok
689
690 CALL libc_errno(SB)
691 MOVLQSX (AX), AX
692 MOVQ (4*8)(SP), DI
693 MOVQ AX, (13*8)(DI) // err
694
695 ok:
696 XORL AX, AX // no error (it's ignored anyway)
697 MOVQ BP, SP
698 POPQ BP
699 RET
700
701 // syscall10X calls a function in libc on behalf of the syscall package.
702 // syscall10X takes a pointer to a struct like:
703 // struct {
704 // fn uintptr
705 // a1 uintptr
706 // a2 uintptr
707 // a3 uintptr
708 // a4 uintptr
709 // a5 uintptr
710 // a6 uintptr
711 // a7 uintptr
712 // a8 uintptr
713 // a9 uintptr
714 // a10 uintptr
715 // r1 uintptr
716 // r2 uintptr
717 // err uintptr
718 // }
719 // syscall10X must be called on the g0 stack with the
720 // C calling convention (use libcCall).
721 //
722 // syscall10X is like syscall10 but expects a 64-bit result
723 // and tests for 64-bit -1 to decide there was an error.
724 TEXT runtime·syscall10X(SB),NOSPLIT,$0
725 PUSHQ BP
726 MOVQ SP, BP
727 SUBQ $48, SP
728
729 // Arguments a1 to a6 get passed in registers, with a7 onwards being
730 // passed via the stack per the x86-64 System V ABI
731 // (https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf).
732 MOVQ (7*8)(DI), R10 // a7
733 MOVQ (8*8)(DI), R11 // a8
734 MOVQ (9*8)(DI), R12 // a9
735 MOVQ (10*8)(DI), R13 // a10
736 MOVQ R10, (0*8)(SP) // a7
737 MOVQ R11, (1*8)(SP) // a8
738 MOVQ R12, (2*8)(SP) // a9
739 MOVQ R13, (3*8)(SP) // a10
740 MOVQ (0*8)(DI), R11 // fn
741 MOVQ (2*8)(DI), SI // a2
742 MOVQ (3*8)(DI), DX // a3
743 MOVQ (4*8)(DI), CX // a4
744 MOVQ (5*8)(DI), R8 // a5
745 MOVQ (6*8)(DI), R9 // a6
746 MOVQ DI, (4*8)(SP)
747 MOVQ (1*8)(DI), DI // a1
748 XORL AX, AX // vararg: say "no float args"
749
750 CALL R11
751
752 MOVQ (4*8)(SP), DI
753 MOVQ AX, (11*8)(DI) // r1
754 MOVQ DX, (12*8)(DI) // r2
755
756 CMPQ AX, $-1
757 JNE ok
758
759 CALL libc_errno(SB)
760 MOVLQSX (AX), AX
761 MOVQ (4*8)(SP), DI
762 MOVQ AX, (13*8)(DI) // err
763
764 ok:
765 XORL AX, AX // no error (it's ignored anyway)
766 MOVQ BP, SP
767 POPQ BP
768 RET
769
View as plain text