Text file src/runtime/sys_darwin_arm64.s
1 // Copyright 2015 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 ARM64, Darwin
6 // System calls are implemented in libSystem, this file contains
7 // trampolines that convert from Go to C calling convention.
8
9 #include "go_asm.h"
10 #include "go_tls.h"
11 #include "textflag.h"
12
13 TEXT notok<>(SB),NOSPLIT,$0
14 MOVD $0, R8
15 MOVD R8, (R8)
16 B 0(PC)
17
18 TEXT runtime·open_trampoline(SB),NOSPLIT,$0
19 SUB $16, RSP
20 MOVW 8(R0), R1 // arg 2 flags
21 MOVW 12(R0), R2 // arg 3 mode
22 MOVW R2, (RSP) // arg 3 is variadic, pass on stack
23 MOVD 0(R0), R0 // arg 1 pathname
24 BL libc_open(SB)
25 ADD $16, RSP
26 RET
27
28 TEXT runtime·close_trampoline(SB),NOSPLIT,$0
29 MOVW 0(R0), R0 // arg 1 fd
30 BL libc_close(SB)
31 RET
32
33 TEXT runtime·write_trampoline(SB),NOSPLIT,$0
34 MOVD 8(R0), R1 // arg 2 buf
35 MOVW 16(R0), R2 // arg 3 count
36 MOVW 0(R0), R0 // arg 1 fd
37 BL libc_write(SB)
38 RET
39
40 TEXT runtime·read_trampoline(SB),NOSPLIT,$0
41 MOVD 8(R0), R1 // arg 2 buf
42 MOVW 16(R0), R2 // arg 3 count
43 MOVW 0(R0), R0 // arg 1 fd
44 BL libc_read(SB)
45 RET
46
47 TEXT runtime·pipe_trampoline(SB),NOSPLIT,$0
48 BL libc_pipe(SB) // pointer already in R0
49 CMP $0, R0
50 BEQ 3(PC)
51 BL libc_error(SB) // return negative errno value
52 NEG R0, R0
53 RET
54
55 TEXT runtime·exit_trampoline(SB),NOSPLIT|NOFRAME,$0
56 MOVW 0(R0), R0
57 BL libc_exit(SB)
58 MOVD $1234, R0
59 MOVD $1002, R1
60 MOVD R0, (R1) // fail hard
61
62 TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
63 MOVD 0(R0), R19 // signal
64 BL libc_getpid(SB)
65 // arg 1 pid already in R0 from getpid
66 MOVD R19, R1 // arg 2 signal
67 BL libc_kill(SB)
68 RET
69
70 TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
71 MOVD R0, R19
72 MOVD 0(R19), R0 // arg 1 addr
73 MOVD 8(R19), R1 // arg 2 len
74 MOVW 16(R19), R2 // arg 3 prot
75 MOVW 20(R19), R3 // arg 4 flags
76 MOVW 24(R19), R4 // arg 5 fd
77 MOVW 28(R19), R5 // arg 6 off
78 BL libc_mmap(SB)
79 MOVD $0, R1
80 MOVD $-1, R2
81 CMP R0, R2
82 BNE ok
83 BL libc_error(SB)
84 MOVW (R0), R1
85 MOVD $0, R0
86 ok:
87 MOVD R0, 32(R19) // ret 1 p
88 MOVD R1, 40(R19) // ret 2 err
89 RET
90
91 TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
92 MOVD 8(R0), R1 // arg 2 len
93 MOVD 0(R0), R0 // arg 1 addr
94 BL libc_munmap(SB)
95 CMP $0, R0
96 BEQ 2(PC)
97 BL notok<>(SB)
98 RET
99
100 TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
101 MOVD 8(R0), R1 // arg 2 len
102 MOVW 16(R0), R2 // arg 3 advice
103 MOVD 0(R0), R0 // arg 1 addr
104 BL libc_madvise(SB)
105 RET
106
107 TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
108 MOVD 8(R0), R1 // arg 2 new
109 MOVD 16(R0), R2 // arg 3 old
110 MOVW 0(R0), R0 // arg 1 which
111 BL libc_setitimer(SB)
112 RET
113
114 TEXT runtime·walltime_trampoline(SB),NOSPLIT,$0
115 // R0 already has *timeval
116 MOVD $0, R1 // no timezone needed
117 BL libc_gettimeofday(SB)
118 RET
119
120 GLOBL timebase<>(SB),NOPTR,$(machTimebaseInfo__size)
121
122 TEXT runtime·nanotime_trampoline(SB),NOSPLIT,$40
123 MOVD R0, R19
124 BL libc_mach_absolute_time(SB)
125 MOVD R0, 0(R19)
126 MOVW timebase<>+machTimebaseInfo_numer(SB), R20
127 MOVD $timebase<>+machTimebaseInfo_denom(SB), R21
128 LDARW (R21), R21 // atomic read
129 CMP $0, R21
130 BNE initialized
131
132 SUB $(machTimebaseInfo__size+15)/16*16, RSP
133 MOVD RSP, R0
134 BL libc_mach_timebase_info(SB)
135 MOVW machTimebaseInfo_numer(RSP), R20
136 MOVW machTimebaseInfo_denom(RSP), R21
137 ADD $(machTimebaseInfo__size+15)/16*16, RSP
138
139 MOVW R20, timebase<>+machTimebaseInfo_numer(SB)
140 MOVD $timebase<>+machTimebaseInfo_denom(SB), R22
141 STLRW R21, (R22) // atomic write
142
143 initialized:
144 MOVW R20, 8(R19)
145 MOVW R21, 12(R19)
146 RET
147
148 TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
149 MOVW sig+8(FP), R0
150 MOVD info+16(FP), R1
151 MOVD ctx+24(FP), R2
152 MOVD fn+0(FP), R11
153 BL (R11)
154 RET
155
156 TEXT runtime·sigtramp(SB),NOSPLIT,$192
157 // Save callee-save registers in the case of signal forwarding.
158 // Please refer to https://golang.org/issue/31827 .
159 MOVD R19, 8*4(RSP)
160 MOVD R20, 8*5(RSP)
161 MOVD R21, 8*6(RSP)
162 MOVD R22, 8*7(RSP)
163 MOVD R23, 8*8(RSP)
164 MOVD R24, 8*9(RSP)
165 MOVD R25, 8*10(RSP)
166 MOVD R26, 8*11(RSP)
167 MOVD R27, 8*12(RSP)
168 MOVD g, 8*13(RSP)
169 MOVD R29, 8*14(RSP)
170 FMOVD F8, 8*15(RSP)
171 FMOVD F9, 8*16(RSP)
172 FMOVD F10, 8*17(RSP)
173 FMOVD F11, 8*18(RSP)
174 FMOVD F12, 8*19(RSP)
175 FMOVD F13, 8*20(RSP)
176 FMOVD F14, 8*21(RSP)
177 FMOVD F15, 8*22(RSP)
178
179 // Save arguments.
180 MOVW R0, (8*1)(RSP) // sig
181 MOVD R1, (8*2)(RSP) // info
182 MOVD R2, (8*3)(RSP) // ctx
183
184 // this might be called in external code context,
185 // where g is not set.
186 MOVB runtime·iscgo(SB), R0
187 CMP $0, R0
188 BEQ 2(PC)
189 BL runtime·load_g(SB)
190
191 MOVD RSP, R6
192 CMP $0, g
193 BEQ nog
194 // iOS always use the main stack to run the signal handler.
195 // We need to switch to gsignal ourselves.
196 MOVD g_m(g), R11
197 MOVD m_gsignal(R11), R5
198 MOVD (g_stack+stack_hi)(R5), R6
199
200 nog:
201 // Restore arguments.
202 MOVW (8*1)(RSP), R0
203 MOVD (8*2)(RSP), R1
204 MOVD (8*3)(RSP), R2
205
206 // Reserve space for args and the stack pointer on the
207 // gsignal stack.
208 SUB $48, R6
209 // Save stack pointer.
210 MOVD RSP, R4
211 MOVD R4, (8*4)(R6)
212 // Switch to gsignal stack.
213 MOVD R6, RSP
214
215 // Call sigtrampgo.
216 MOVW R0, (8*1)(RSP)
217 MOVD R1, (8*2)(RSP)
218 MOVD R2, (8*3)(RSP)
219 MOVD $runtime·sigtrampgo(SB), R11
220 BL (R11)
221
222 // Switch to old stack.
223 MOVD (8*4)(RSP), R5
224 MOVD R5, RSP
225
226 // Restore callee-save registers.
227 MOVD (8*4)(RSP), R19
228 MOVD (8*5)(RSP), R20
229 MOVD (8*6)(RSP), R21
230 MOVD (8*7)(RSP), R22
231 MOVD (8*8)(RSP), R23
232 MOVD (8*9)(RSP), R24
233 MOVD (8*10)(RSP), R25
234 MOVD (8*11)(RSP), R26
235 MOVD (8*12)(RSP), R27
236 MOVD (8*13)(RSP), g
237 MOVD (8*14)(RSP), R29
238 FMOVD (8*15)(RSP), F8
239 FMOVD (8*16)(RSP), F9
240 FMOVD (8*17)(RSP), F10
241 FMOVD (8*18)(RSP), F11
242 FMOVD (8*19)(RSP), F12
243 FMOVD (8*20)(RSP), F13
244 FMOVD (8*21)(RSP), F14
245 FMOVD (8*22)(RSP), F15
246
247 RET
248
249 TEXT runtime·cgoSigtramp(SB),NOSPLIT,$0
250 JMP runtime·sigtramp(SB)
251
252 TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
253 MOVD 8(R0), R1 // arg 2 new
254 MOVD 16(R0), R2 // arg 3 old
255 MOVW 0(R0), R0 // arg 1 how
256 BL libc_pthread_sigmask(SB)
257 CMP $0, R0
258 BEQ 2(PC)
259 BL notok<>(SB)
260 RET
261
262 TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
263 MOVD 8(R0), R1 // arg 2 new
264 MOVD 16(R0), R2 // arg 3 old
265 MOVW 0(R0), R0 // arg 1 how
266 BL libc_sigaction(SB)
267 CMP $0, R0
268 BEQ 2(PC)
269 BL notok<>(SB)
270 RET
271
272 TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
273 MOVW 0(R0), R0 // arg 1 usec
274 BL libc_usleep(SB)
275 RET
276
277 TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
278 MOVW 8(R0), R1 // arg 2 miblen
279 MOVD 16(R0), R2 // arg 3 out
280 MOVD 24(R0), R3 // arg 4 size
281 MOVD 32(R0), R4 // arg 5 dst
282 MOVD 40(R0), R5 // arg 6 ndst
283 MOVD 0(R0), R0 // arg 1 mib
284 BL libc_sysctl(SB)
285 RET
286
287 TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
288 BL libc_kqueue(SB)
289 RET
290
291 TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
292 MOVD 8(R0), R1 // arg 2 keventt
293 MOVW 16(R0), R2 // arg 3 nch
294 MOVD 24(R0), R3 // arg 4 ev
295 MOVW 32(R0), R4 // arg 5 nev
296 MOVD 40(R0), R5 // arg 6 ts
297 MOVW 0(R0), R0 // arg 1 kq
298 BL libc_kevent(SB)
299 MOVD $-1, R2
300 CMP R0, R2
301 BNE ok
302 BL libc_error(SB)
303 MOVW (R0), R0 // errno
304 NEG R0, R0 // caller wants it as a negative error code
305 ok:
306 RET
307
308 TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
309 SUB $16, RSP
310 MOVW 4(R0), R1 // arg 2 cmd
311 MOVW 8(R0), R2 // arg 3 arg
312 MOVW R2, (RSP) // arg 3 is variadic, pass on stack
313 MOVW 0(R0), R0 // arg 1 fd
314 BL libc_fcntl(SB)
315 ADD $16, RSP
316 RET
317
318 // sigaltstack on iOS is not supported and will always
319 // run the signal handler on the main stack, so our sigtramp has
320 // to do the stack switch ourselves.
321 TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
322 MOVW $43, R0
323 BL libc_exit(SB)
324 RET
325
326 // Thread related functions
327
328 // mstart_stub is the first function executed on a new thread started by pthread_create.
329 // It just does some low-level setup and then calls mstart.
330 // Note: called with the C calling convention.
331 TEXT runtime·mstart_stub(SB),NOSPLIT,$160
332 // R0 points to the m.
333 // We are already on m's g0 stack.
334
335 // Save callee-save registers.
336 MOVD R19, 8(RSP)
337 MOVD R20, 16(RSP)
338 MOVD R21, 24(RSP)
339 MOVD R22, 32(RSP)
340 MOVD R23, 40(RSP)
341 MOVD R24, 48(RSP)
342 MOVD R25, 56(RSP)
343 MOVD R26, 64(RSP)
344 MOVD R27, 72(RSP)
345 MOVD g, 80(RSP)
346 MOVD R29, 88(RSP)
347 FMOVD F8, 96(RSP)
348 FMOVD F9, 104(RSP)
349 FMOVD F10, 112(RSP)
350 FMOVD F11, 120(RSP)
351 FMOVD F12, 128(RSP)
352 FMOVD F13, 136(RSP)
353 FMOVD F14, 144(RSP)
354 FMOVD F15, 152(RSP)
355
356 MOVD m_g0(R0), g
357
358 BL runtime·mstart(SB)
359
360 // Restore callee-save registers.
361 MOVD 8(RSP), R19
362 MOVD 16(RSP), R20
363 MOVD 24(RSP), R21
364 MOVD 32(RSP), R22
365 MOVD 40(RSP), R23
366 MOVD 48(RSP), R24
367 MOVD 56(RSP), R25
368 MOVD 64(RSP), R26
369 MOVD 72(RSP), R27
370 MOVD 80(RSP), g
371 MOVD 88(RSP), R29
372 FMOVD 96(RSP), F8
373 FMOVD 104(RSP), F9
374 FMOVD 112(RSP), F10
375 FMOVD 120(RSP), F11
376 FMOVD 128(RSP), F12
377 FMOVD 136(RSP), F13
378 FMOVD 144(RSP), F14
379 FMOVD 152(RSP), F15
380
381 // Go is all done with this OS thread.
382 // Tell pthread everything is ok (we never join with this thread, so
383 // the value here doesn't really matter).
384 MOVD $0, R0
385
386 RET
387
388 TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
389 MOVD 0(R0), R0 // arg 1 attr
390 BL libc_pthread_attr_init(SB)
391 RET
392
393 TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
394 MOVD 8(R0), R1 // arg 2 size
395 MOVD 0(R0), R0 // arg 1 attr
396 BL libc_pthread_attr_getstacksize(SB)
397 RET
398
399 TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
400 MOVD 8(R0), R1 // arg 2 state
401 MOVD 0(R0), R0 // arg 1 attr
402 BL libc_pthread_attr_setdetachstate(SB)
403 RET
404
405 TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
406 SUB $16, RSP
407 MOVD 0(R0), R1 // arg 2 state
408 MOVD 8(R0), R2 // arg 3 start
409 MOVD 16(R0), R3 // arg 4 arg
410 MOVD RSP, R0 // arg 1 &threadid (which we throw away)
411 BL libc_pthread_create(SB)
412 ADD $16, RSP
413 RET
414
415 TEXT runtime·raise_trampoline(SB),NOSPLIT,$0
416 MOVW 0(R0), R0 // arg 1 sig
417 BL libc_raise(SB)
418 RET
419
420 TEXT runtime·pthread_mutex_init_trampoline(SB),NOSPLIT,$0
421 MOVD 8(R0), R1 // arg 2 attr
422 MOVD 0(R0), R0 // arg 1 mutex
423 BL libc_pthread_mutex_init(SB)
424 RET
425
426 TEXT runtime·pthread_mutex_lock_trampoline(SB),NOSPLIT,$0
427 MOVD 0(R0), R0 // arg 1 mutex
428 BL libc_pthread_mutex_lock(SB)
429 RET
430
431 TEXT runtime·pthread_mutex_unlock_trampoline(SB),NOSPLIT,$0
432 MOVD 0(R0), R0 // arg 1 mutex
433 BL libc_pthread_mutex_unlock(SB)
434 RET
435
436 TEXT runtime·pthread_cond_init_trampoline(SB),NOSPLIT,$0
437 MOVD 8(R0), R1 // arg 2 attr
438 MOVD 0(R0), R0 // arg 1 cond
439 BL libc_pthread_cond_init(SB)
440 RET
441
442 TEXT runtime·pthread_cond_wait_trampoline(SB),NOSPLIT,$0
443 MOVD 8(R0), R1 // arg 2 mutex
444 MOVD 0(R0), R0 // arg 1 cond
445 BL libc_pthread_cond_wait(SB)
446 RET
447
448 TEXT runtime·pthread_cond_timedwait_relative_np_trampoline(SB),NOSPLIT,$0
449 MOVD 8(R0), R1 // arg 2 mutex
450 MOVD 16(R0), R2 // arg 3 timeout
451 MOVD 0(R0), R0 // arg 1 cond
452 BL libc_pthread_cond_timedwait_relative_np(SB)
453 RET
454
455 TEXT runtime·pthread_cond_signal_trampoline(SB),NOSPLIT,$0
456 MOVD 0(R0), R0 // arg 1 cond
457 BL libc_pthread_cond_signal(SB)
458 RET
459
460 // syscall calls a function in libc on behalf of the syscall package.
461 // syscall takes a pointer to a struct like:
462 // struct {
463 // fn uintptr
464 // a1 uintptr
465 // a2 uintptr
466 // a3 uintptr
467 // r1 uintptr
468 // r2 uintptr
469 // err uintptr
470 // }
471 // syscall must be called on the g0 stack with the
472 // C calling convention (use libcCall).
473 TEXT runtime·syscall(SB),NOSPLIT,$0
474 SUB $16, RSP // push structure pointer
475 MOVD R0, 8(RSP)
476
477 MOVD 0(R0), R12 // fn
478 MOVD 16(R0), R1 // a2
479 MOVD 24(R0), R2 // a3
480 MOVD 8(R0), R0 // a1
481
482 // If fn is declared as vararg, we have to pass the vararg arguments on the stack.
483 // (Because ios decided not to adhere to the standard arm64 calling convention, sigh...)
484 // The only libSystem calls we support that are vararg are open, fcntl, and ioctl,
485 // which are all of the form fn(x, y, ...). So we just need to put the 3rd arg
486 // on the stack as well.
487 // If we ever have other vararg libSystem calls, we might need to handle more cases.
488 MOVD R2, (RSP)
489
490 BL (R12)
491
492 MOVD 8(RSP), R2 // pop structure pointer
493 ADD $16, RSP
494 MOVD R0, 32(R2) // save r1
495 MOVD R1, 40(R2) // save r2
496 CMPW $-1, R0
497 BNE ok
498 SUB $16, RSP // push structure pointer
499 MOVD R2, 8(RSP)
500 BL libc_error(SB)
501 MOVW (R0), R0
502 MOVD 8(RSP), R2 // pop structure pointer
503 ADD $16, RSP
504 MOVD R0, 48(R2) // save err
505 ok:
506 RET
507
508 // syscallX calls a function in libc on behalf of the syscall package.
509 // syscallX takes a pointer to a struct like:
510 // struct {
511 // fn uintptr
512 // a1 uintptr
513 // a2 uintptr
514 // a3 uintptr
515 // r1 uintptr
516 // r2 uintptr
517 // err uintptr
518 // }
519 // syscallX must be called on the g0 stack with the
520 // C calling convention (use libcCall).
521 TEXT runtime·syscallX(SB),NOSPLIT,$0
522 SUB $16, RSP // push structure pointer
523 MOVD R0, (RSP)
524
525 MOVD 0(R0), R12 // fn
526 MOVD 16(R0), R1 // a2
527 MOVD 24(R0), R2 // a3
528 MOVD 8(R0), R0 // a1
529 BL (R12)
530
531 MOVD (RSP), R2 // pop structure pointer
532 ADD $16, RSP
533 MOVD R0, 32(R2) // save r1
534 MOVD R1, 40(R2) // save r2
535 CMP $-1, R0
536 BNE ok
537 SUB $16, RSP // push structure pointer
538 MOVD R2, (RSP)
539 BL libc_error(SB)
540 MOVW (R0), R0
541 MOVD (RSP), R2 // pop structure pointer
542 ADD $16, RSP
543 MOVD R0, 48(R2) // save err
544 ok:
545 RET
546
547 // syscallPtr is like syscallX except that the libc function reports an
548 // error by returning NULL and setting errno.
549 TEXT runtime·syscallPtr(SB),NOSPLIT,$0
550 SUB $16, RSP // push structure pointer
551 MOVD R0, (RSP)
552
553 MOVD 0(R0), R12 // fn
554 MOVD 16(R0), R1 // a2
555 MOVD 24(R0), R2 // a3
556 MOVD 8(R0), R0 // a1
557 BL (R12)
558
559 MOVD (RSP), R2 // pop structure pointer
560 ADD $16, RSP
561 MOVD R0, 32(R2) // save r1
562 MOVD R1, 40(R2) // save r2
563 CMP $0, R0
564 BNE ok
565 SUB $16, RSP // push structure pointer
566 MOVD R2, (RSP)
567 BL libc_error(SB)
568 MOVW (R0), R0
569 MOVD (RSP), R2 // pop structure pointer
570 ADD $16, RSP
571 MOVD R0, 48(R2) // save err
572 ok:
573 RET
574
575 // syscall6 calls a function in libc on behalf of the syscall package.
576 // syscall6 takes a pointer to a struct like:
577 // struct {
578 // fn uintptr
579 // a1 uintptr
580 // a2 uintptr
581 // a3 uintptr
582 // a4 uintptr
583 // a5 uintptr
584 // a6 uintptr
585 // r1 uintptr
586 // r2 uintptr
587 // err uintptr
588 // }
589 // syscall6 must be called on the g0 stack with the
590 // C calling convention (use libcCall).
591 TEXT runtime·syscall6(SB),NOSPLIT,$0
592 SUB $16, RSP // push structure pointer
593 MOVD R0, 8(RSP)
594
595 MOVD 0(R0), R12 // fn
596 MOVD 16(R0), R1 // a2
597 MOVD 24(R0), R2 // a3
598 MOVD 32(R0), R3 // a4
599 MOVD 40(R0), R4 // a5
600 MOVD 48(R0), R5 // a6
601 MOVD 8(R0), R0 // a1
602
603 // If fn is declared as vararg, we have to pass the vararg arguments on the stack.
604 // See syscall above. The only function this applies to is openat, for which the 4th
605 // arg must be on the stack.
606 MOVD R3, (RSP)
607
608 BL (R12)
609
610 MOVD 8(RSP), R2 // pop structure pointer
611 ADD $16, RSP
612 MOVD R0, 56(R2) // save r1
613 MOVD R1, 64(R2) // save r2
614 CMPW $-1, R0
615 BNE ok
616 SUB $16, RSP // push structure pointer
617 MOVD R2, 8(RSP)
618 BL libc_error(SB)
619 MOVW (R0), R0
620 MOVD 8(RSP), R2 // pop structure pointer
621 ADD $16, RSP
622 MOVD R0, 72(R2) // save err
623 ok:
624 RET
625
626 // syscall6X calls a function in libc on behalf of the syscall package.
627 // syscall6X takes a pointer to a struct like:
628 // struct {
629 // fn uintptr
630 // a1 uintptr
631 // a2 uintptr
632 // a3 uintptr
633 // a4 uintptr
634 // a5 uintptr
635 // a6 uintptr
636 // r1 uintptr
637 // r2 uintptr
638 // err uintptr
639 // }
640 // syscall6X must be called on the g0 stack with the
641 // C calling convention (use libcCall).
642 TEXT runtime·syscall6X(SB),NOSPLIT,$0
643 SUB $16, RSP // push structure pointer
644 MOVD R0, (RSP)
645
646 MOVD 0(R0), R12 // fn
647 MOVD 16(R0), R1 // a2
648 MOVD 24(R0), R2 // a3
649 MOVD 32(R0), R3 // a4
650 MOVD 40(R0), R4 // a5
651 MOVD 48(R0), R5 // a6
652 MOVD 8(R0), R0 // a1
653 BL (R12)
654
655 MOVD (RSP), R2 // pop structure pointer
656 ADD $16, RSP
657 MOVD R0, 56(R2) // save r1
658 MOVD R1, 64(R2) // save r2
659 CMP $-1, R0
660 BNE ok
661 SUB $16, RSP // push structure pointer
662 MOVD R2, (RSP)
663 BL libc_error(SB)
664 MOVW (R0), R0
665 MOVD (RSP), R2 // pop structure pointer
666 ADD $16, RSP
667 MOVD R0, 72(R2) // save err
668 ok:
669 RET
View as plain text