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