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 ARM, OpenBSD
6// /usr/src/sys/kern/syscalls.master for syscall numbers.
7//
8
9#include "go_asm.h"
10#include "go_tls.h"
11#include "textflag.h"
12
13#define	CLOCK_REALTIME	$0
14#define	CLOCK_MONOTONIC	$3
15
16// With OpenBSD 6.7 onwards, an armv7 syscall returns two instructions
17// after the SWI instruction, to allow for a speculative execution
18// barrier to be placed after the SWI without impacting performance.
19// For now use hardware no-ops as this works with both older and newer
20// kernels. After OpenBSD 6.8 is released this should be changed to
21// speculation barriers.
22#define NOOP	MOVW    R0, R0
23#define	INVOKE_SYSCALL	\
24	SWI	$0;	\
25	NOOP;		\
26	NOOP
27
28// mstart_stub is the first function executed on a new thread started by pthread_create.
29// It just does some low-level setup and then calls mstart.
30// Note: called with the C calling convention.
31TEXT runtime·mstart_stub(SB),NOSPLIT,$0
32	// R0 points to the m.
33	// We are already on m's g0 stack.
34
35	// Save callee-save registers.
36	MOVM.DB.W [R4-R11], (R13)
37
38	MOVW	m_g0(R0), g
39	BL	runtime·save_g(SB)
40
41	BL	runtime·mstart(SB)
42
43	// Restore callee-save registers.
44	MOVM.IA.W (R13), [R4-R11]
45
46	// Go is all done with this OS thread.
47	// Tell pthread everything is ok (we never join with this thread, so
48	// the value here doesn't really matter).
49	MOVW	$0, R0
50	RET
51
52TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
53	MOVW	sig+4(FP), R0
54	MOVW	info+8(FP), R1
55	MOVW	ctx+12(FP), R2
56	MOVW	fn+0(FP), R3
57	MOVW	R13, R9
58	SUB	$24, R13
59	BIC	$0x7, R13 // alignment for ELF ABI
60	BL	(R3)
61	MOVW	R9, R13
62	RET
63
64TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$0
65	// Reserve space for callee-save registers and arguments.
66	MOVM.DB.W [R4-R11], (R13)
67	SUB	$16, R13
68
69	// If called from an external code context, g will not be set.
70	// Save R0, since runtime·load_g will clobber it.
71	MOVW	R0, 4(R13)		// signum
72	BL	runtime·load_g(SB)
73
74	MOVW	R1, 8(R13)
75	MOVW	R2, 12(R13)
76	BL	runtime·sigtrampgo(SB)
77
78	// Restore callee-save registers.
79	ADD	$16, R13
80	MOVM.IA.W (R13), [R4-R11]
81
82	RET
83
84TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
85	B	runtime·armPublicationBarrier(SB)
86
87// TODO(jsing): OpenBSD only supports GOARM=7 machines... this
88// should not be needed, however the linker still allows GOARM=5
89// on this platform.
90TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
91	MOVM.WP	[R1, R2, R3, R12], (R13)
92	MOVW	$330, R12		// sys___get_tcb
93	INVOKE_SYSCALL
94	MOVM.IAW (R13), [R1, R2, R3, R12]
95	RET
96
97// These trampolines help convert from Go calling convention to C calling convention.
98// They should be called with asmcgocall - note that while asmcgocall does
99// stack alignment, creation of a frame undoes it again.
100// A pointer to the arguments is passed in R0.
101// A single int32 result is returned in R0.
102// (For more results, make an args/results structure.)
103TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
104	MOVW	R13, R9
105	BIC     $0x7, R13		// align for ELF ABI
106	MOVW	0(R0), R0		// arg 1 attr
107	CALL	libc_pthread_attr_init(SB)
108	MOVW	R9, R13
109	RET
110
111TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0
112	MOVW	R13, R9
113	BIC     $0x7, R13		// align for ELF ABI
114	MOVW	0(R0), R0		// arg 1 attr
115	CALL	libc_pthread_attr_destroy(SB)
116	MOVW	R9, R13
117	RET
118
119TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
120	MOVW	R13, R9
121	BIC     $0x7, R13		// align for ELF ABI
122	MOVW	4(R0), R1		// arg 2 size
123	MOVW	0(R0), R0		// arg 1 attr
124	CALL	libc_pthread_attr_getstacksize(SB)
125	MOVW	R9, R13
126	RET
127
128TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
129	MOVW	R13, R9
130	BIC     $0x7, R13		// align for ELF ABI
131	MOVW	4(R0), R1		// arg 2 state
132	MOVW	0(R0), R0		// arg 1 attr
133	CALL	libc_pthread_attr_setdetachstate(SB)
134	MOVW	R9, R13
135	RET
136
137TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
138	MOVW	R13, R9
139	SUB	$16, R13
140	BIC     $0x7, R13		// align for ELF ABI
141	MOVW	0(R0), R1		// arg 2 attr
142	MOVW	4(R0), R2		// arg 3 start
143	MOVW	8(R0), R3		// arg 4 arg
144	MOVW	R13, R0			// arg 1 &threadid (discarded)
145	CALL	libc_pthread_create(SB)
146	MOVW	R9, R13
147	RET
148
149TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
150	MOVW	R13, R9
151	BIC     $0x7, R13		// align for ELF ABI
152	MOVW	4(R0), R1		// arg 2 - signal
153	MOVW	$0, R2			// arg 3 - tcb
154	MOVW	0(R0), R0		// arg 1 - tid
155	CALL	libc_thrkill(SB)
156	MOVW	R9, R13
157	RET
158
159TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
160	MOVW	R13, R9
161	SUB	$16, R13
162	BIC     $0x7, R13		// align for ELF ABI
163	MOVW	4(R0), R1		// arg 2 - clock_id
164	MOVW	8(R0), R2		// arg 3 - abstime
165	MOVW	12(R0), R3		// arg 4 - lock
166	MOVW	16(R0), R4		// arg 5 - abort (on stack)
167	MOVW	R4, 0(R13)
168	MOVW	0(R0), R0		// arg 1 - id
169	CALL	libc_thrsleep(SB)
170	MOVW	R9, R13
171	RET
172
173TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
174	MOVW	R13, R9
175	BIC     $0x7, R13		// align for ELF ABI
176	MOVW	4(R0), R1		// arg 2 - count
177	MOVW	0(R0), R0		// arg 1 - id
178	CALL	libc_thrwakeup(SB)
179	MOVW	R9, R13
180	RET
181
182TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
183	MOVW	R13, R9
184	BIC     $0x7, R13		// align for ELF ABI
185	MOVW	0(R0), R0		// arg 1 exit status
186	BL	libc_exit(SB)
187	MOVW	$0, R8			// crash on failure
188	MOVW	R8, (R8)
189	MOVW	R9, R13
190	RET
191
192TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
193	MOVW	R13, R9
194	MOVW	R0, R8
195	BIC     $0x7, R13		// align for ELF ABI
196	BL	libc_getthrid(SB)
197	MOVW	R0, 0(R8)
198	MOVW	R9, R13
199	RET
200
201TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
202	MOVW	R13, R9
203	BIC     $0x7, R13		// align for ELF ABI
204	MOVW	R0, R4
205	BL	libc_getpid(SB)		// arg 1 pid
206	MOVW	R4, R1			// arg 2 signal
207	BL	libc_kill(SB)
208	MOVW	R9, R13
209	RET
210
211TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
212	MOVW	R13, R9
213	BIC     $0x7, R13		// align for ELF ABI
214	BL	libc_sched_yield(SB)
215	MOVW	R9, R13
216	RET
217
218TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
219	MOVW	R13, R9
220	SUB	$16, R13
221	BIC     $0x7, R13		// align for ELF ABI
222	MOVW	R0, R8
223	MOVW	4(R0), R1		// arg 2 len
224	MOVW	8(R0), R2		// arg 3 prot
225	MOVW	12(R0), R3		// arg 4 flags
226	MOVW	16(R0), R4		// arg 5 fid (on stack)
227	MOVW	R4, 0(R13)
228	MOVW	$0, R5			// pad (on stack)
229	MOVW	R5, 4(R13)
230	MOVW	20(R0), R6		// arg 6 offset (on stack)
231	MOVW	R6, 8(R13)		// low 32 bits
232	MOVW    $0, R7
233	MOVW	R7, 12(R13)		// high 32 bits
234	MOVW	0(R0), R0		// arg 1 addr
235	BL	libc_mmap(SB)
236	MOVW	$0, R1
237	CMP	$-1, R0
238	BNE	ok
239	BL	libc_errno(SB)
240	MOVW	(R0), R1		// errno
241	MOVW	$0, R0
242ok:
243	MOVW	R0, 24(R8)
244	MOVW	R1, 28(R8)
245	MOVW	R9, R13
246	RET
247
248TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
249	MOVW	R13, R9
250	BIC     $0x7, R13		// align for ELF ABI
251	MOVW	4(R0), R1		// arg 2 len
252	MOVW	0(R0), R0		// arg 1 addr
253	BL	libc_munmap(SB)
254	CMP	$-1, R0
255	BNE	3(PC)
256	MOVW	$0, R8			// crash on failure
257	MOVW	R8, (R8)
258	MOVW	R9, R13
259	RET
260
261TEXT runtime·madvise_trampoline(SB), NOSPLIT, $0
262	MOVW	R13, R9
263	BIC     $0x7, R13		// align for ELF ABI
264	MOVW	4(R0), R1		// arg 2 len
265	MOVW	8(R0), R2		// arg 3 advice
266	MOVW	0(R0), R0		// arg 1 addr
267	BL	libc_madvise(SB)
268	// ignore failure - maybe pages are locked
269	MOVW	R9, R13
270	RET
271
272TEXT runtime·open_trampoline(SB),NOSPLIT,$0
273	MOVW	R13, R9
274	SUB	$8, R13
275	BIC     $0x7, R13		// align for ELF ABI
276	MOVW	4(R0), R1		// arg 2 - flags
277	MOVW	8(R0), R2		// arg 3 - mode (vararg, on stack)
278	MOVW	R2, 0(R13)
279	MOVW	0(R0), R0		// arg 1 - path
280	MOVW	R13, R4
281	BIC     $0x7, R13		// align for ELF ABI
282	BL	libc_open(SB)
283	MOVW	R9, R13
284	RET
285
286TEXT runtime·close_trampoline(SB),NOSPLIT,$0
287	MOVW	R13, R9
288	BIC     $0x7, R13		// align for ELF ABI
289	MOVW	0(R0), R0		// arg 1 - fd
290	BL	libc_close(SB)
291	MOVW	R9, R13
292	RET
293
294TEXT runtime·read_trampoline(SB),NOSPLIT,$0
295	MOVW	R13, R9
296	BIC     $0x7, R13		// align for ELF ABI
297	MOVW	4(R0), R1		// arg 2 - buf
298	MOVW	8(R0), R2		// arg 3 - count
299	MOVW	0(R0), R0		// arg 1 - fd
300	BL	libc_read(SB)
301	CMP	$-1, R0
302	BNE	noerr
303	BL	libc_errno(SB)
304	MOVW	(R0), R0		// errno
305	RSB.CS	$0, R0			// caller expects negative errno
306noerr:
307	MOVW	R9, R13
308	RET
309
310TEXT runtime·write_trampoline(SB),NOSPLIT,$0
311	MOVW	R13, R9
312	BIC     $0x7, R13		// align for ELF ABI
313	MOVW	4(R0), R1		// arg 2 buf
314	MOVW	8(R0), R2		// arg 3 count
315	MOVW	0(R0), R0		// arg 1 fd
316	BL	libc_write(SB)
317	CMP	$-1, R0
318	BNE	noerr
319	BL	libc_errno(SB)
320	MOVW	(R0), R0		// errno
321	RSB.CS	$0, R0			// caller expects negative errno
322noerr:
323	MOVW	R9, R13
324	RET
325
326TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
327	MOVW	R13, R9
328	BIC     $0x7, R13		// align for ELF ABI
329	MOVW	4(R0), R1		// arg 2 flags
330	MOVW	0(R0), R0		// arg 1 filedes
331	BL	libc_pipe2(SB)
332	CMP	$-1, R0
333	BNE	3(PC)
334	BL	libc_errno(SB)
335	MOVW	(R0), R0		// errno
336	RSB.CS	$0, R0			// caller expects negative errno
337	MOVW	R9, R13
338	RET
339
340TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
341	MOVW	R13, R9
342	BIC     $0x7, R13		// align for ELF ABI
343	MOVW	4(R0), R1		// arg 2 new
344	MOVW	8(R0), R2		// arg 3 old
345	MOVW	0(R0), R0		// arg 1 which
346	BL	libc_setitimer(SB)
347	MOVW	R9, R13
348	RET
349
350TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
351	MOVW	R13, R9
352	BIC     $0x7, R13		// align for ELF ABI
353	MOVW	0(R0), R0		// arg 1 usec
354	BL	libc_usleep(SB)
355	MOVW	R9, R13
356	RET
357
358TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
359	MOVW	R13, R9
360	SUB	$8, R13
361	BIC     $0x7, R13		// align for ELF ABI
362	MOVW	4(R0), R1		// arg 2 miblen
363	MOVW	8(R0), R2		// arg 3 out
364	MOVW	12(R0), R3		// arg 4 size
365	MOVW	16(R0), R4		// arg 5 dst (on stack)
366	MOVW	R4, 0(R13)
367	MOVW	20(R0), R5		// arg 6 ndst (on stack)
368	MOVW	R5, 4(R13)
369	MOVW	0(R0), R0		// arg 1 mib
370	BL	libc_sysctl(SB)
371	MOVW	R9, R13
372	RET
373
374TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
375	MOVW	R13, R9
376	BIC     $0x7, R13		// align for ELF ABI
377	BL	libc_kqueue(SB)
378	MOVW	R9, R13
379	RET
380
381TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
382	MOVW	R13, R9
383	SUB	$8, R13
384	BIC     $0x7, R13		// align for ELF ABI
385	MOVW	4(R0), R1		// arg 2 keventt
386	MOVW	8(R0), R2		// arg 3 nch
387	MOVW	12(R0), R3		// arg 4 ev
388	MOVW	16(R0), R4		// arg 5 nev (on stack)
389	MOVW	R4, 0(R13)
390	MOVW	20(R0), R5		// arg 6 ts (on stack)
391	MOVW	R5, 4(R13)
392	MOVW	0(R0), R0		// arg 1 kq
393	BL	libc_kevent(SB)
394	CMP	$-1, R0
395	BNE	ok
396	BL	libc_errno(SB)
397	MOVW	(R0), R0		// errno
398	RSB.CS	$0, R0			// caller expects negative errno
399ok:
400	MOVW	R9, R13
401	RET
402
403TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
404	MOVW	R13, R9
405	BIC     $0x7, R13		// align for ELF ABI
406	MOVW	4(R0), R1		// arg 2 tp
407	MOVW	0(R0), R0		// arg 1 clock_id
408	BL	libc_clock_gettime(SB)
409	CMP	$-1, R0
410	BNE	noerr
411	BL	libc_errno(SB)
412	MOVW	(R0), R0		// errno
413	RSB.CS	$0, R0			// caller expects negative errno
414noerr:
415	MOVW	R9, R13
416	RET
417
418TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
419	MOVW	R13, R9
420	SUB	$8, R13
421	BIC     $0x7, R13		// align for ELF ABI
422	MOVW	R0, R8
423	MOVW	0(R8), R0		// arg 1 fd
424	MOVW	4(R8), R1		// arg 2 cmd
425	MOVW	8(R8), R2		// arg 3 arg (vararg, on stack)
426	MOVW	R2, 0(R13)
427	BL	libc_fcntl(SB)
428	MOVW	$0, R1
429	CMP	$-1, R0
430	BNE	noerr
431	BL	libc_errno(SB)
432	MOVW	(R0), R1
433	MOVW	$-1, R0
434noerr:
435	MOVW	R0, 12(R8)
436	MOVW	R1, 16(R8)
437	MOVW	R9, R13
438	RET
439
440TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
441	MOVW	R13, R9
442	BIC     $0x7, R13		// align for ELF ABI
443	MOVW	4(R0), R1		// arg 2 new
444	MOVW	8(R0), R2		// arg 3 old
445	MOVW	0(R0), R0		// arg 1 sig
446	BL	libc_sigaction(SB)
447	CMP	$-1, R0
448	BNE	3(PC)
449	MOVW	$0, R8			// crash on failure
450	MOVW	R8, (R8)
451	MOVW	R9, R13
452	RET
453
454TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
455	MOVW	R13, R9
456	BIC     $0x7, R13		// align for ELF ABI
457	MOVW	4(R0), R1		// arg 2 new
458	MOVW	8(R0), R2		// arg 3 old
459	MOVW	0(R0), R0		// arg 1 how
460	BL	libc_pthread_sigmask(SB)
461	CMP	$-1, R0
462	BNE	3(PC)
463	MOVW	$0, R8			// crash on failure
464	MOVW	R8, (R8)
465	MOVW	R9, R13
466	RET
467
468TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
469	MOVW	R13, R9
470	BIC     $0x7, R13		// align for ELF ABI
471	MOVW	4(R0), R1		// arg 2 old
472	MOVW	0(R0), R0		// arg 1 new
473	BL	libc_sigaltstack(SB)
474	CMP	$-1, R0
475	BNE	3(PC)
476	MOVW	$0, R8			// crash on failure
477	MOVW	R8, (R8)
478	MOVW	R9, R13
479	RET
480
481// syscall calls a function in libc on behalf of the syscall package.
482// syscall takes a pointer to a struct like:
483// struct {
484//	fn    uintptr
485//	a1    uintptr
486//	a2    uintptr
487//	a3    uintptr
488//	r1    uintptr
489//	r2    uintptr
490//	err   uintptr
491// }
492// syscall must be called on the g0 stack with the
493// C calling convention (use libcCall).
494//
495// syscall expects a 32-bit result and tests for 32-bit -1
496// to decide there was an error.
497TEXT runtime·syscall(SB),NOSPLIT,$0
498	MOVW	R13, R9
499	BIC     $0x7, R13		// align for ELF ABI
500
501	MOVW	R0, R8
502
503	MOVW	(0*4)(R8), R7 // fn
504	MOVW	(1*4)(R8), R0 // a1
505	MOVW	(2*4)(R8), R1 // a2
506	MOVW	(3*4)(R8), R2 // a3
507
508	BL	(R7)
509
510	MOVW	R0, (4*4)(R8) // r1
511	MOVW	R1, (5*4)(R8) // r2
512
513	// Standard libc functions return -1 on error and set errno.
514	CMP	$-1, R0
515	BNE	ok
516
517	// Get error code from libc.
518	BL	libc_errno(SB)
519	MOVW	(R0), R1
520	MOVW	R1, (6*4)(R8) // err
521
522ok:
523	MOVW	$0, R0		// no error (it's ignored anyway)
524	MOVW	R9, R13
525	RET
526
527// syscallX calls a function in libc on behalf of the syscall package.
528// syscallX takes a pointer to a struct like:
529// struct {
530//	fn    uintptr
531//	a1    uintptr
532//	a2    uintptr
533//	a3    uintptr
534//	r1    uintptr
535//	r2    uintptr
536//	err   uintptr
537// }
538// syscallX must be called on the g0 stack with the
539// C calling convention (use libcCall).
540//
541// syscallX is like syscall but expects a 64-bit result
542// and tests for 64-bit -1 to decide there was an error.
543TEXT runtime·syscallX(SB),NOSPLIT,$0
544	MOVW	R13, R9
545	BIC     $0x7, R13		// align for ELF ABI
546
547	MOVW	R0, R8
548
549	MOVW	(0*4)(R8), R7 // fn
550	MOVW	(1*4)(R8), R0 // a1
551	MOVW	(2*4)(R8), R1 // a2
552	MOVW	(3*4)(R8), R2 // a3
553
554	BL	(R7)
555
556	MOVW	R0, (4*4)(R8) // r1
557	MOVW	R1, (5*4)(R8) // r2
558
559	// Standard libc functions return -1 on error and set errno.
560	CMP	$-1, R0
561	BNE	ok
562	CMP	$-1, R1
563	BNE	ok
564
565	// Get error code from libc.
566	BL	libc_errno(SB)
567	MOVW	(R0), R1
568	MOVW	R1, (6*4)(R8) // err
569
570ok:
571	MOVW	$0, R0		// no error (it's ignored anyway)
572	MOVW	R9, R13
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//
592// syscall6 expects a 32-bit result and tests for 32-bit -1
593// to decide there was an error.
594TEXT runtime·syscall6(SB),NOSPLIT,$0
595	MOVW	R13, R9
596	SUB	$8, R13
597	BIC     $0x7, R13		// align for ELF ABI
598
599	MOVW	R0, R8
600
601	MOVW	(0*4)(R8), R7 // fn
602	MOVW	(1*4)(R8), R0 // a1
603	MOVW	(2*4)(R8), R1 // a2
604	MOVW	(3*4)(R8), R2 // a3
605	MOVW	(4*4)(R8), R3 // a4
606	MOVW	(5*4)(R8), R4 // a5
607	MOVW	R4, 0(R13)
608	MOVW	(6*4)(R8), R5 // a6
609	MOVW	R5, 4(R13)
610
611	BL	(R7)
612
613	MOVW	R0, (7*4)(R8) // r1
614	MOVW	R1, (8*4)(R8) // r2
615
616	// Standard libc functions return -1 on error and set errno.
617	CMP	$-1, R0
618	BNE	ok
619
620	// Get error code from libc.
621	BL	libc_errno(SB)
622	MOVW	(R0), R1
623	MOVW	R1, (9*4)(R8) // err
624
625ok:
626	MOVW	$0, R0		// no error (it's ignored anyway)
627	MOVW	R9, R13
628	RET
629
630// syscall6X calls a function in libc on behalf of the syscall package.
631// syscall6X takes a pointer to a struct like:
632// struct {
633//	fn    uintptr
634//	a1    uintptr
635//	a2    uintptr
636//	a3    uintptr
637//	a4    uintptr
638//	a5    uintptr
639//	a6    uintptr
640//	r1    uintptr
641//	r2    uintptr
642//	err   uintptr
643// }
644// syscall6X must be called on the g0 stack with the
645// C calling convention (use libcCall).
646//
647// syscall6X is like syscall6 but expects a 64-bit result
648// and tests for 64-bit -1 to decide there was an error.
649TEXT runtime·syscall6X(SB),NOSPLIT,$0
650	MOVW	R13, R9
651	SUB	$8, R13
652	BIC     $0x7, R13		// align for ELF ABI
653
654	MOVW	R0, R8
655
656	MOVW	(0*4)(R8), R7 // fn
657	MOVW	(1*4)(R8), R0 // a1
658	MOVW	(2*4)(R8), R1 // a2
659	MOVW	(3*4)(R8), R2 // a3
660	MOVW	(4*4)(R8), R3 // a4
661	MOVW	(5*4)(R8), R4 // a5
662	MOVW	R4, 0(R13)
663	MOVW	(6*4)(R8), R5 // a6
664	MOVW	R5, 4(R13)
665
666	BL	(R7)
667
668	MOVW	R0, (7*4)(R8) // r1
669	MOVW	R1, (8*4)(R8) // r2
670
671	// Standard libc functions return -1 on error and set errno.
672	CMP	$-1, R0
673	BNE	ok
674	CMP	$-1, R1
675	BNE	ok
676
677	// Get error code from libc.
678	BL	libc_errno(SB)
679	MOVW	(R0), R1
680	MOVW	R1, (9*4)(R8) // err
681
682ok:
683	MOVW	$0, R0		// no error (it's ignored anyway)
684	MOVW	R9, R13
685	RET
686
687// syscall10 calls a function in libc on behalf of the syscall package.
688// syscall10 takes a pointer to a struct like:
689// struct {
690//	fn    uintptr
691//	a1    uintptr
692//	a2    uintptr
693//	a3    uintptr
694//	a4    uintptr
695//	a5    uintptr
696//	a6    uintptr
697//	a7    uintptr
698//	a8    uintptr
699//	a9    uintptr
700//	a10   uintptr
701//	r1    uintptr
702//	r2    uintptr
703//	err   uintptr
704// }
705// syscall10 must be called on the g0 stack with the
706// C calling convention (use libcCall).
707TEXT runtime·syscall10(SB),NOSPLIT,$0
708	MOVW	R13, R9
709	SUB	$24, R13
710	BIC     $0x7, R13		// align for ELF ABI
711
712	MOVW	R0, R8
713
714	MOVW	(0*4)(R8), R7 // fn
715	MOVW	(1*4)(R8), R0 // a1
716	MOVW	(2*4)(R8), R1 // a2
717	MOVW	(3*4)(R8), R2 // a3
718	MOVW	(4*4)(R8), R3 // a4
719	MOVW	(5*4)(R8), R4 // a5
720	MOVW	R4, 0(R13)
721	MOVW	(6*4)(R8), R5 // a6
722	MOVW	R5, 4(R13)
723	MOVW	(7*4)(R8), R6 // a7
724	MOVW	R6, 8(R13)
725	MOVW	(8*4)(R8), R4 // a8
726	MOVW	R4, 12(R13)
727	MOVW	(9*4)(R8), R5 // a9
728	MOVW	R5, 16(R13)
729	MOVW	(10*4)(R8), R6 // a10
730	MOVW	R6, 20(R13)
731
732	BL	(R7)
733
734	MOVW	R0, (11*4)(R8) // r1
735	MOVW	R1, (12*4)(R8) // r2
736
737	// Standard libc functions return -1 on error and set errno.
738	CMP	$-1, R0
739	BNE	ok
740
741	// Get error code from libc.
742	BL	libc_errno(SB)
743	MOVW	(R0), R1
744	MOVW	R1, (13*4)(R8) // err
745
746ok:
747	MOVW	$0, R0		// no error (it's ignored anyway)
748	MOVW	R9, R13
749	RET
750
751// syscall10X calls a function in libc on behalf of the syscall package.
752// syscall10X takes a pointer to a struct like:
753// struct {
754//	fn    uintptr
755//	a1    uintptr
756//	a2    uintptr
757//	a3    uintptr
758//	a4    uintptr
759//	a5    uintptr
760//	a6    uintptr
761//	a7    uintptr
762//	a8    uintptr
763//	a9    uintptr
764//	a10   uintptr
765//	r1    uintptr
766//	r2    uintptr
767//	err   uintptr
768// }
769// syscall10X must be called on the g0 stack with the
770// C calling convention (use libcCall).
771//
772// syscall10X is like syscall10 but expects a 64-bit result
773// and tests for 64-bit -1 to decide there was an error.
774TEXT runtime·syscall10X(SB),NOSPLIT,$0
775	MOVW	R13, R9
776	SUB	$24, R13
777	BIC     $0x7, R13		// align for ELF ABI
778
779	MOVW	R0, R8
780
781	MOVW	(0*4)(R8), R7 // fn
782	MOVW	(1*4)(R8), R0 // a1
783	MOVW	(2*4)(R8), R1 // a2
784	MOVW	(3*4)(R8), R2 // a3
785	MOVW	(4*4)(R8), R3 // a4
786	MOVW	(5*4)(R8), R4 // a5
787	MOVW	R4, 0(R13)
788	MOVW	(6*4)(R8), R5 // a6
789	MOVW	R5, 4(R13)
790	MOVW	(7*4)(R8), R6 // a7
791	MOVW	R6, 8(R13)
792	MOVW	(8*4)(R8), R4 // a8
793	MOVW	R4, 12(R13)
794	MOVW	(9*4)(R8), R5 // a9
795	MOVW	R5, 16(R13)
796	MOVW	(10*4)(R8), R6 // a10
797	MOVW	R6, 20(R13)
798
799	BL	(R7)
800
801	MOVW	R0, (11*4)(R8) // r1
802	MOVW	R1, (12*4)(R8) // r2
803
804	// Standard libc functions return -1 on error and set errno.
805	CMP	$-1, R0
806	BNE	ok
807	CMP	$-1, R1
808	BNE	ok
809
810	// Get error code from libc.
811	BL	libc_errno(SB)
812	MOVW	(R0), R1
813	MOVW	R1, (13*4)(R8) // err
814
815ok:
816	MOVW	$0, R0		// no error (it's ignored anyway)
817	MOVW	R9, R13
818	RET
819
820TEXT runtime·issetugid_trampoline(SB),NOSPLIT,$0
821	MOVW	R13, R9
822	MOVW	R0, R8
823	BIC     $0x7, R13		// align for ELF ABI
824	BL	libc_issetugid(SB)
825	MOVW	R0, 0(R8)
826	MOVW	R9, R13
827	RET
828