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 386, 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
15#define	CLOCK_MONOTONIC	$3
16
17TEXT runtime·setldt(SB),NOSPLIT,$0
18	// Nothing to do, pthread already set thread-local storage up.
19	RET
20
21// mstart_stub is the first function executed on a new thread started by pthread_create.
22// It just does some low-level setup and then calls mstart.
23// Note: called with the C calling convention.
24TEXT runtime·mstart_stub(SB),NOSPLIT,$28
25	NOP	SP	// tell vet SP changed - stop checking offsets
26
27	// We are already on m's g0 stack.
28
29	// Save callee-save registers.
30	MOVL	BX, bx-4(SP)
31	MOVL	BP, bp-8(SP)
32	MOVL	SI, si-12(SP)
33	MOVL	DI, di-16(SP)
34
35	MOVL	32(SP), AX	// m
36	MOVL	m_g0(AX), DX
37	get_tls(CX)
38	MOVL	DX, g(CX)
39
40	CALL	runtime·mstart(SB)
41
42	// Restore callee-save registers.
43	MOVL	di-16(SP), DI
44	MOVL	si-12(SP), SI
45	MOVL	bp-8(SP),  BP
46	MOVL	bx-4(SP),  BX
47
48	// Go is all done with this OS thread.
49	// Tell pthread everything is ok (we never join with this thread, so
50	// the value here doesn't really matter).
51	MOVL	$0, AX
52	RET
53
54TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
55	MOVL	fn+0(FP), AX
56	MOVL	sig+4(FP), BX
57	MOVL	info+8(FP), CX
58	MOVL	ctx+12(FP), DX
59	MOVL	SP, SI
60	SUBL	$32, SP
61	ANDL	$~15, SP	// align stack: handler might be a C function
62	MOVL	BX, 0(SP)
63	MOVL	CX, 4(SP)
64	MOVL	DX, 8(SP)
65	MOVL	SI, 12(SP)	// save SI: handler might be a Go function
66	CALL	AX
67	MOVL	12(SP), AX
68	MOVL	AX, SP
69	RET
70
71// Called by OS using C ABI.
72TEXT runtime·sigtramp(SB),NOSPLIT|TOPFRAME,$28
73	NOP	SP	// tell vet SP changed - stop checking offsets
74	// Save callee-saved C registers, since the caller may be a C signal handler.
75	MOVL	BX, bx-4(SP)
76	MOVL	BP, bp-8(SP)
77	MOVL	SI, si-12(SP)
78	MOVL	DI, di-16(SP)
79	// We don't save mxcsr or the x87 control word because sigtrampgo doesn't
80	// modify them.
81
82	MOVL	32(SP), BX // signo
83	MOVL	BX, 0(SP)
84	MOVL	36(SP), BX // info
85	MOVL	BX, 4(SP)
86	MOVL	40(SP), BX // context
87	MOVL	BX, 8(SP)
88	CALL	runtime·sigtrampgo(SB)
89
90	MOVL	di-16(SP), DI
91	MOVL	si-12(SP), SI
92	MOVL	bp-8(SP),  BP
93	MOVL	bx-4(SP),  BX
94	RET
95
96// These trampolines help convert from Go calling convention to C calling convention.
97// They should be called with asmcgocall - note that while asmcgocall does
98// stack alignment, creation of a frame undoes it again.
99// A pointer to the arguments is passed on the stack.
100// A single int32 result is returned in AX.
101// (For more results, make an args/results structure.)
102TEXT runtime·pthread_attr_init_trampoline(SB),NOSPLIT,$0
103	PUSHL	BP
104	MOVL	SP, BP
105	SUBL	$4, SP
106	MOVL	12(SP), DX		// pointer to args
107	MOVL	0(DX), AX
108	MOVL	AX, 0(SP)		// arg 1 - attr
109	CALL	libc_pthread_attr_init(SB)
110	MOVL	BP, SP
111	POPL	BP
112	RET
113
114TEXT runtime·pthread_attr_destroy_trampoline(SB),NOSPLIT,$0
115	PUSHL	BP
116	MOVL	SP, BP
117	SUBL	$4, SP
118	MOVL	12(SP), DX		// pointer to args
119	MOVL	0(DX), AX
120	MOVL	AX, 0(SP)		// arg 1 - attr
121	CALL	libc_pthread_attr_destroy(SB)
122	MOVL	BP, SP
123	POPL	BP
124	RET
125
126TEXT runtime·pthread_attr_getstacksize_trampoline(SB),NOSPLIT,$0
127	PUSHL	BP
128	MOVL	SP, BP
129	SUBL	$8, SP
130	MOVL	16(SP), DX		// pointer to args
131	MOVL	0(DX), AX
132	MOVL	4(DX), BX
133	MOVL	AX, 0(SP)		// arg 1 - attr
134	MOVL	BX, 4(SP)		// arg 2 - size
135	CALL	libc_pthread_attr_getstacksize(SB)
136	MOVL	BP, SP
137	POPL	BP
138	RET
139
140TEXT runtime·pthread_attr_setdetachstate_trampoline(SB),NOSPLIT,$0
141	PUSHL	BP
142	MOVL	SP, BP
143	SUBL	$8, SP
144	MOVL	16(SP), DX		// pointer to args
145	MOVL	0(DX), AX
146	MOVL	4(DX), BX
147	MOVL	AX, 0(SP)		// arg 1 - attr
148	MOVL	BX, 4(SP)		// arg 2 - state
149	CALL	libc_pthread_attr_setdetachstate(SB)
150	MOVL	BP, SP
151	POPL	BP
152	RET
153
154TEXT runtime·pthread_create_trampoline(SB),NOSPLIT,$0
155	PUSHL	BP
156	MOVL	SP, BP
157	SUBL	$20, SP
158	MOVL	28(SP), DX		// pointer to args
159	LEAL	16(SP), AX
160	MOVL	AX, 0(SP)		// arg 1 - &threadid (discarded)
161	MOVL	0(DX), AX
162	MOVL	4(DX), BX
163	MOVL	8(DX), CX
164	MOVL	AX, 4(SP)		// arg 2 - attr
165	MOVL	BX, 8(SP)		// arg 3 - start
166	MOVL	CX, 12(SP)		// arg 4 - arg
167	CALL	libc_pthread_create(SB)
168	MOVL	BP, SP
169	POPL	BP
170	RET
171
172TEXT runtime·thrkill_trampoline(SB),NOSPLIT,$0
173	PUSHL	BP
174	MOVL	SP, BP
175	SUBL	$12, SP
176	MOVL	20(SP), DX		// pointer to args
177	MOVL	0(DX), AX
178	MOVL	4(DX), BX
179	MOVL	AX, 0(SP)		// arg 1 - tid
180	MOVL	BX, 4(SP)		// arg 2 - signal
181	MOVL	$0, 8(SP)		// arg 3 - tcb
182	CALL	libc_thrkill(SB)
183	MOVL	BP, SP
184	POPL	BP
185	RET
186
187TEXT runtime·thrsleep_trampoline(SB),NOSPLIT,$0
188	PUSHL	BP
189	MOVL	SP, BP
190	SUBL	$20, SP
191	MOVL	28(SP), DX		// pointer to args
192	MOVL	0(DX), AX
193	MOVL	4(DX), BX
194	MOVL	8(DX), CX
195	MOVL	AX, 0(SP)		// arg 1 - id
196	MOVL	BX, 4(SP)		// arg 2 - clock_id
197	MOVL	CX, 8(SP)		// arg 3 - abstime
198	MOVL	12(DX), AX
199	MOVL	16(DX), BX
200	MOVL	AX, 12(SP)		// arg 4 - lock
201	MOVL	BX, 16(SP)		// arg 5 - abort
202	CALL	libc_thrsleep(SB)
203	MOVL	BP, SP
204	POPL	BP
205	RET
206
207TEXT runtime·thrwakeup_trampoline(SB),NOSPLIT,$0
208	PUSHL	BP
209	MOVL	SP, BP
210	SUBL	$8, SP
211	MOVL	16(SP), DX		// pointer to args
212	MOVL	0(DX), AX
213	MOVL	4(DX), BX
214	MOVL	AX, 0(SP)		// arg 1 - id
215	MOVL	BX, 4(SP)		// arg 2 - count
216	CALL	libc_thrwakeup(SB)
217	MOVL	BP, SP
218	POPL	BP
219	RET
220
221TEXT runtime·exit_trampoline(SB),NOSPLIT,$0
222	PUSHL	BP
223	MOVL	SP, BP
224	SUBL	$4, SP
225	MOVL	12(SP), DX		// pointer to args
226	MOVL	0(DX), AX
227	MOVL	AX, 0(SP)		// arg 1 - status
228	CALL	libc_exit(SB)
229	MOVL	$0xf1, 0xf1		// crash on failure
230	MOVL	BP, SP
231	POPL	BP
232	RET
233
234TEXT runtime·getthrid_trampoline(SB),NOSPLIT,$0
235	PUSHL	BP
236	CALL	libc_getthrid(SB)
237	NOP	SP			// tell vet SP changed - stop checking offsets
238	MOVL	8(SP), DX		// pointer to return value
239	MOVL	AX, 0(DX)
240	POPL	BP
241	RET
242
243TEXT runtime·raiseproc_trampoline(SB),NOSPLIT,$0
244	PUSHL	BP
245	MOVL	SP, BP
246	SUBL	$8, SP
247	MOVL	16(SP), DX
248	MOVL	0(DX), BX
249	CALL	libc_getpid(SB)
250	MOVL	AX, 0(SP)		// arg 1 - pid
251	MOVL	BX, 4(SP)		// arg 2 - signal
252	CALL	libc_kill(SB)
253	MOVL	BP, SP
254	POPL	BP
255	RET
256
257TEXT runtime·sched_yield_trampoline(SB),NOSPLIT,$0
258	PUSHL	BP
259	MOVL	SP, BP
260	CALL	libc_sched_yield(SB)
261	MOVL	BP, SP
262	POPL	BP
263	RET
264
265TEXT runtime·mmap_trampoline(SB),NOSPLIT,$0
266	PUSHL	BP
267	MOVL	SP, BP
268	SUBL	$32, SP
269	MOVL	40(SP), DX		// pointer to args
270	MOVL	0(DX), AX
271	MOVL	4(DX), BX
272	MOVL	8(DX), CX
273	MOVL	AX, 0(SP)		// arg 1 - addr
274	MOVL	BX, 4(SP)		// arg 2 - len
275	MOVL	CX, 8(SP)		// arg 3 - prot
276	MOVL	12(DX), AX
277	MOVL	16(DX), BX
278	MOVL	20(DX), CX
279	MOVL	AX, 12(SP)		// arg 4 - flags
280	MOVL	BX, 16(SP)		// arg 5 - fid
281	MOVL	$0, 20(SP)		// pad
282	MOVL	CX, 24(SP)		// arg 6 - offset (low 32 bits)
283	MOVL	$0, 28(SP)		// offset (high 32 bits)
284	CALL	libc_mmap(SB)
285	MOVL	$0, BX
286	CMPL	AX, $-1
287	JNE	ok
288	CALL	libc_errno(SB)
289	MOVL	(AX), BX
290	MOVL	$0, AX
291ok:
292	MOVL	40(SP), DX
293	MOVL	AX, 24(DX)
294	MOVL	BX, 28(DX)
295	MOVL	BP, SP
296	POPL	BP
297	RET
298
299TEXT runtime·munmap_trampoline(SB),NOSPLIT,$0
300	PUSHL	BP
301	MOVL	SP, BP
302	SUBL	$8, SP
303	MOVL	16(SP), DX		// pointer to args
304	MOVL	0(DX), AX
305	MOVL	4(DX), BX
306	MOVL	AX, 0(SP)		// arg 1 - addr
307	MOVL	BX, 4(SP)		// arg 2 - len
308	CALL	libc_munmap(SB)
309	CMPL	AX, $-1
310	JNE	2(PC)
311	MOVL	$0xf1, 0xf1		// crash on failure
312	MOVL	BP, SP
313	POPL	BP
314	RET
315
316TEXT runtime·madvise_trampoline(SB),NOSPLIT,$0
317	PUSHL	BP
318	MOVL	SP, BP
319	SUBL	$12, SP
320	MOVL	20(SP), DX		// pointer to args
321	MOVL	0(DX), AX
322	MOVL	4(DX), BX
323	MOVL	8(DX), CX
324	MOVL	AX, 0(SP)		// arg 1 - addr
325	MOVL	BX, 4(SP)		// arg 2 - len
326	MOVL	CX, 8(SP)		// arg 3 - advice
327	CALL	libc_madvise(SB)
328	// ignore failure - maybe pages are locked
329	MOVL	BP, SP
330	POPL	BP
331	RET
332
333TEXT runtime·open_trampoline(SB),NOSPLIT,$0
334	PUSHL	BP
335	MOVL	SP, BP
336	SUBL	$16, SP
337	MOVL	24(SP), DX		// pointer to args
338	MOVL	0(DX), AX
339	MOVL	4(DX), BX
340	MOVL	8(DX), CX
341	MOVL	AX, 0(SP)		// arg 1 - path
342	MOVL	BX, 4(SP)		// arg 2 - flags
343	MOVL	CX, 8(SP)		// arg 3 - mode
344	MOVL	$0, 12(SP)		// vararg
345	CALL	libc_open(SB)
346	MOVL	BP, SP
347	POPL	BP
348	RET
349
350TEXT runtime·close_trampoline(SB),NOSPLIT,$0
351	PUSHL	BP
352	MOVL	SP, BP
353	SUBL	$4, SP
354	MOVL	12(SP), DX
355	MOVL	0(DX), AX
356	MOVL	AX, 0(SP)		// arg 1 - fd
357	CALL	libc_close(SB)
358	MOVL	BP, SP
359	POPL	BP
360	RET
361
362TEXT runtime·read_trampoline(SB),NOSPLIT,$0
363	PUSHL	BP
364	MOVL	SP, BP
365	SUBL	$12, SP
366	MOVL	20(SP), DX		// pointer to args
367	MOVL	0(DX), AX
368	MOVL	4(DX), BX
369	MOVL	8(DX), CX
370	MOVL	AX, 0(SP)		// arg 1 - fd
371	MOVL	BX, 4(SP)		// arg 2 - buf
372	MOVL	CX, 8(SP)		// arg 3 - count
373	CALL	libc_read(SB)
374	CMPL	AX, $-1
375	JNE	noerr
376	CALL	libc_errno(SB)
377	MOVL	(AX), AX
378	NEGL	AX			// caller expects negative errno
379noerr:
380	MOVL	BP, SP
381	POPL	BP
382	RET
383
384TEXT runtime·write_trampoline(SB),NOSPLIT,$0
385	PUSHL	BP
386	MOVL	SP, BP
387	SUBL	$12, SP
388	MOVL	20(SP), DX		// pointer to args
389	MOVL	0(DX), AX
390	MOVL	4(DX), BX
391	MOVL	8(DX), CX
392	MOVL	AX, 0(SP)		// arg 1 - fd
393	MOVL	BX, 4(SP)		// arg 2 - buf
394	MOVL	CX, 8(SP)		// arg 3 - count
395	CALL	libc_write(SB)
396	CMPL	AX, $-1
397	JNE	noerr
398	CALL	libc_errno(SB)
399	MOVL	(AX), AX
400	NEGL	AX			// caller expects negative errno
401noerr:
402	MOVL	BP, SP
403	POPL	BP
404	RET
405
406TEXT runtime·pipe2_trampoline(SB),NOSPLIT,$0
407	PUSHL	BP
408	MOVL	SP, BP
409	SUBL	$8, SP
410	MOVL	16(SP), DX		// pointer to args
411	MOVL	0(DX), AX
412	MOVL	4(DX), BX
413	MOVL	AX, 0(SP)		// arg 1 - fds
414	MOVL	BX, 4(SP)		// arg 2 - flags
415	CALL	libc_pipe2(SB)
416	CMPL	AX, $-1
417	JNE	noerr
418	CALL	libc_errno(SB)
419	MOVL	(AX), AX
420	NEGL	AX			// caller expects negative errno
421noerr:
422	MOVL	BP, SP
423	POPL	BP
424	RET
425
426TEXT runtime·setitimer_trampoline(SB),NOSPLIT,$0
427	PUSHL	BP
428	MOVL	SP, BP
429	SUBL	$12, SP
430	MOVL	20(SP), DX		// pointer to args
431	MOVL	0(DX), AX
432	MOVL	4(DX), BX
433	MOVL	8(DX), CX
434	MOVL	AX, 0(SP)		// arg 1 - which
435	MOVL	BX, 4(SP)		// arg 2 - new
436	MOVL	CX, 8(SP)		// arg 3 - old
437	CALL	libc_setitimer(SB)
438	MOVL	BP, SP
439	POPL	BP
440	RET
441
442TEXT runtime·usleep_trampoline(SB),NOSPLIT,$0
443	PUSHL	BP
444	MOVL	SP, BP
445	SUBL	$4, SP
446	MOVL	12(SP), DX		// pointer to args
447	MOVL	0(DX), AX
448	MOVL	AX, 0(SP)
449	CALL	libc_usleep(SB)
450	MOVL	BP, SP
451	POPL	BP
452	RET
453
454TEXT runtime·sysctl_trampoline(SB),NOSPLIT,$0
455	PUSHL	BP
456	MOVL	SP, BP
457	SUBL	$24, SP
458	MOVL	32(SP), DX		// pointer to args
459	MOVL	0(DX), AX
460	MOVL	4(DX), BX
461	MOVL	8(DX), CX
462	MOVL	AX, 0(SP)		// arg 1 - name
463	MOVL	BX, 4(SP)		// arg 2 - namelen
464	MOVL	CX, 8(SP)		// arg 3 - old
465	MOVL	12(DX), AX
466	MOVL	16(DX), BX
467	MOVL	20(DX), CX
468	MOVL	AX, 12(SP)		// arg 4 - oldlenp
469	MOVL	BX, 16(SP)		// arg 5 - newp
470	MOVL	CX, 20(SP)		// arg 6 - newlen
471	CALL	libc_sysctl(SB)
472	MOVL	BP, SP
473	POPL	BP
474	RET
475
476TEXT runtime·kqueue_trampoline(SB),NOSPLIT,$0
477	PUSHL	BP
478	MOVL	SP, BP
479	CALL	libc_kqueue(SB)
480	MOVL	BP, SP
481	POPL	BP
482	RET
483
484TEXT runtime·kevent_trampoline(SB),NOSPLIT,$0
485	PUSHL	BP
486	MOVL	SP, BP
487	SUBL	$24, SP
488	MOVL	32(SP), DX		// pointer to args
489	MOVL	0(DX), AX
490	MOVL	4(DX), BX
491	MOVL	8(DX), CX
492	MOVL	AX, 0(SP)		// arg 1 - kq
493	MOVL	BX, 4(SP)		// arg 2 - keventt
494	MOVL	CX, 8(SP)		// arg 3 - nch
495	MOVL	12(DX), AX
496	MOVL	16(DX), BX
497	MOVL	20(DX), CX
498	MOVL	AX, 12(SP)		// arg 4 - ev
499	MOVL	BX, 16(SP)		// arg 5 - nev
500	MOVL	CX, 20(SP)		// arg 6 - ts
501	CALL	libc_kevent(SB)
502	CMPL	AX, $-1
503	JNE	noerr
504	CALL	libc_errno(SB)
505	MOVL	(AX), AX
506	NEGL	AX			// caller expects negative errno
507noerr:
508	MOVL	BP, SP
509	POPL	BP
510	RET
511
512TEXT runtime·clock_gettime_trampoline(SB),NOSPLIT,$0
513	PUSHL	BP
514	MOVL	SP, BP
515	SUBL	$8, SP
516	MOVL	16(SP), DX		// pointer to args
517	MOVL	0(DX), AX
518	MOVL	4(DX), BX
519	MOVL	AX, 0(SP)		// arg 1 - tp
520	MOVL	BX, 4(SP)		// arg 2 - clock_id
521	CALL	libc_clock_gettime(SB)
522	CMPL	AX, $-1
523	JNE	noerr
524	CALL	libc_errno(SB)
525	MOVL	(AX), AX
526	NEGL	AX			// caller expects negative errno
527noerr:
528	MOVL	BP, SP
529	POPL	BP
530	RET
531
532TEXT runtime·fcntl_trampoline(SB),NOSPLIT,$0
533	PUSHL	BP
534	MOVL	SP, BP
535	SUBL	$16, SP
536	MOVL	24(SP), DX		// pointer to args
537	MOVL	0(DX), AX
538	MOVL	4(DX), BX
539	MOVL	8(DX), CX
540	MOVL	AX, 0(SP)		// arg 1 - fd
541	MOVL	BX, 4(SP)		// arg 2 - cmd
542	MOVL	CX, 8(SP)		// arg 3 - arg
543	MOVL	$0, 12(SP)		// vararg
544	CALL	libc_fcntl(SB)
545	MOVL	$0, BX
546	CMPL	AX, $-1
547	JNE	noerr
548	CALL	libc_errno(SB)
549	MOVL	(AX), BX
550	MOVL	$-1, AX
551noerr:
552	MOVL	24(SP), DX		// pointer to args
553	MOVL	AX, 12(DX)
554	MOVL	BX, 16(DX)
555	MOVL	BP, SP
556	POPL	BP
557	RET
558
559TEXT runtime·sigaction_trampoline(SB),NOSPLIT,$0
560	PUSHL	BP
561	MOVL	SP, BP
562	SUBL	$12, SP
563	MOVL	20(SP), DX		// pointer to args
564	MOVL	0(DX), AX
565	MOVL	4(DX), BX
566	MOVL	8(DX), CX
567	MOVL	AX, 0(SP)		// arg 1 - sig
568	MOVL	BX, 4(SP)		// arg 2 - new
569	MOVL	CX, 8(SP)		// arg 3 - old
570	CALL	libc_sigaction(SB)
571	CMPL	AX, $-1
572	JNE	2(PC)
573	MOVL	$0xf1, 0xf1		// crash on failure
574	MOVL	BP, SP
575	POPL	BP
576	RET
577
578TEXT runtime·sigprocmask_trampoline(SB),NOSPLIT,$0
579	PUSHL	BP
580	MOVL	SP, BP
581	SUBL	$12, SP
582	MOVL	20(SP), DX		// pointer to args
583	MOVL	0(DX), AX
584	MOVL	4(DX), BX
585	MOVL	8(DX), CX
586	MOVL	AX, 0(SP)		// arg 1 - how
587	MOVL	BX, 4(SP)		// arg 2 - new
588	MOVL	CX, 8(SP)		// arg 3 - old
589	CALL	libc_pthread_sigmask(SB)
590	CMPL	AX, $-1
591	JNE	2(PC)
592	MOVL	$0xf1, 0xf1		// crash on failure
593	MOVL	BP, SP
594	POPL	BP
595	RET
596
597TEXT runtime·sigaltstack_trampoline(SB),NOSPLIT,$0
598	PUSHL	BP
599	MOVL	SP, BP
600	SUBL	$8, SP
601	MOVL	16(SP), DX		// pointer to args
602	MOVL	0(DX), AX
603	MOVL	4(DX), BX
604	MOVL	AX, 0(SP)		// arg 1 - new
605	MOVL	BX, 4(SP)		// arg 2 - old
606	CALL	libc_sigaltstack(SB)
607	CMPL	AX, $-1
608	JNE	2(PC)
609	MOVL	$0xf1, 0xf1		// crash on failure
610	MOVL	BP, SP
611	POPL	BP
612	RET
613
614// syscall calls a function in libc on behalf of the syscall package.
615// syscall takes a pointer to a struct like:
616// struct {
617//	fn    uintptr
618//	a1    uintptr
619//	a2    uintptr
620//	a3    uintptr
621//	r1    uintptr
622//	r2    uintptr
623//	err   uintptr
624// }
625// syscall must be called on the g0 stack with the
626// C calling convention (use libcCall).
627//
628// syscall expects a 32-bit result and tests for 32-bit -1
629// to decide there was an error.
630TEXT runtime·syscall(SB),NOSPLIT,$0
631	PUSHL	BP
632	MOVL	SP, BP
633
634	SUBL	$12, SP
635	MOVL	20(SP), BX		// pointer to args
636
637	MOVL	(1*4)(BX), AX
638	MOVL	(2*4)(BX), CX
639	MOVL	(3*4)(BX), DX
640	MOVL	AX, (0*4)(SP)		// a1
641	MOVL	CX, (1*4)(SP)		// a2
642	MOVL	DX, (2*4)(SP)		// a3
643
644	MOVL	(0*4)(BX), AX		// fn
645	CALL	AX
646
647	MOVL	AX, (4*4)(BX)		// r1
648	MOVL	DX, (5*4)(BX)		// r2
649
650	// Standard libc functions return -1 on error and set errno.
651	CMPL	AX, $-1
652	JNE	ok
653
654	// Get error code from libc.
655	CALL	libc_errno(SB)
656	MOVL	(AX), AX
657	MOVW	AX, (6*4)(BX)		// err
658
659ok:
660	MOVL	$0, AX			// no error (it's ignored anyway)
661	MOVL	BP, SP
662	POPL	BP
663	RET
664
665// syscallX calls a function in libc on behalf of the syscall package.
666// syscallX takes a pointer to a struct like:
667// struct {
668//	fn    uintptr
669//	a1    uintptr
670//	a2    uintptr
671//	a3    uintptr
672//	r1    uintptr
673//	r2    uintptr
674//	err   uintptr
675// }
676// syscallX must be called on the g0 stack with the
677// C calling convention (use libcCall).
678//
679// syscallX is like syscall but expects a 64-bit result
680// and tests for 64-bit -1 to decide there was an error.
681TEXT runtime·syscallX(SB),NOSPLIT,$0
682	PUSHL	BP
683	MOVL	SP, BP
684
685	SUBL	$12, SP
686	MOVL	20(SP), BX		// pointer to args
687
688	MOVL	(1*4)(BX), AX
689	MOVL	(2*4)(BX), CX
690	MOVL	(3*4)(BX), DX
691	MOVL	AX, (0*4)(SP)		// a1
692	MOVL	CX, (1*4)(SP)		// a2
693	MOVL	DX, (2*4)(SP)		// a3
694
695	MOVL	(0*4)(BX), AX		// fn
696	CALL	AX
697
698	MOVL	AX, (4*4)(BX)		// r1
699	MOVL	DX, (5*4)(BX)		// r2
700
701	// Standard libc functions return -1 on error and set errno.
702	CMPL	AX, $-1
703	JNE	ok
704	CMPL	DX, $-1
705	JNE	ok
706
707	// Get error code from libc.
708	CALL	libc_errno(SB)
709	MOVL	(AX), AX
710	MOVW	AX, (6*4)(BX)		// err
711
712ok:
713	MOVL	$0, AX			// no error (it's ignored anyway)
714	MOVL	BP, SP
715	POPL	BP
716	RET
717
718// syscall6 calls a function in libc on behalf of the syscall package.
719// syscall6 takes a pointer to a struct like:
720// struct {
721//	fn    uintptr
722//	a1    uintptr
723//	a2    uintptr
724//	a3    uintptr
725//	a4    uintptr
726//	a5    uintptr
727//	a6    uintptr
728//	r1    uintptr
729//	r2    uintptr
730//	err   uintptr
731// }
732// syscall6 must be called on the g0 stack with the
733// C calling convention (use libcCall).
734//
735// syscall6 expects a 32-bit result and tests for 32-bit -1
736// to decide there was an error.
737TEXT runtime·syscall6(SB),NOSPLIT,$0
738	PUSHL	BP
739	MOVL	SP, BP
740
741	SUBL	$24, SP
742	MOVL	32(SP), BX		// pointer to args
743
744	MOVL	(1*4)(BX), AX
745	MOVL	(2*4)(BX), CX
746	MOVL	(3*4)(BX), DX
747	MOVL	AX, (0*4)(SP)		// a1
748	MOVL	CX, (1*4)(SP)		// a2
749	MOVL	DX, (2*4)(SP)		// a3
750	MOVL	(4*4)(BX), AX
751	MOVL	(5*4)(BX), CX
752	MOVL	(6*4)(BX), DX
753	MOVL	AX, (3*4)(SP)		// a4
754	MOVL	CX, (4*4)(SP)		// a5
755	MOVL	DX, (5*4)(SP)		// a6
756
757	MOVL	(0*4)(BX), AX		// fn
758	CALL	AX
759
760	MOVL	AX, (7*4)(BX)		// r1
761	MOVL	DX, (8*4)(BX)		// r2
762
763	// Standard libc functions return -1 on error and set errno.
764	CMPL	AX, $-1
765	JNE	ok
766
767	// Get error code from libc.
768	CALL	libc_errno(SB)
769	MOVL	(AX), AX
770	MOVW	AX, (9*4)(BX)		// err
771
772ok:
773	MOVL	$0, AX			// no error (it's ignored anyway)
774	MOVL	BP, SP
775	POPL	BP
776	RET
777
778// syscall6X calls a function in libc on behalf of the syscall package.
779// syscall6X takes a pointer to a struct like:
780// struct {
781//	fn    uintptr
782//	a1    uintptr
783//	a2    uintptr
784//	a3    uintptr
785//	a4    uintptr
786//	a5    uintptr
787//	a6    uintptr
788//	r1    uintptr
789//	r2    uintptr
790//	err   uintptr
791// }
792// syscall6X must be called on the g0 stack with the
793// C calling convention (use libcCall).
794//
795// syscall6X is like syscall6 but expects a 64-bit result
796// and tests for 64-bit -1 to decide there was an error.
797TEXT runtime·syscall6X(SB),NOSPLIT,$0
798	PUSHL	BP
799	MOVL	SP, BP
800
801	SUBL	$24, SP
802	MOVL	32(SP), BX		// pointer to args
803
804	MOVL	(1*4)(BX), AX
805	MOVL	(2*4)(BX), CX
806	MOVL	(3*4)(BX), DX
807	MOVL	AX, (0*4)(SP)		// a1
808	MOVL	CX, (1*4)(SP)		// a2
809	MOVL	DX, (2*4)(SP)		// a3
810	MOVL	(4*4)(BX), AX
811	MOVL	(5*4)(BX), CX
812	MOVL	(6*4)(BX), DX
813	MOVL	AX, (3*4)(SP)		// a4
814	MOVL	CX, (4*4)(SP)		// a5
815	MOVL	DX, (5*4)(SP)		// a6
816
817	MOVL	(0*4)(BX), AX		// fn
818	CALL	AX
819
820	MOVL	AX, (7*4)(BX)		// r1
821	MOVL	DX, (8*4)(BX)		// r2
822
823	// Standard libc functions return -1 on error and set errno.
824	CMPL	AX, $-1
825	JNE	ok
826	CMPL	DX, $-1
827	JNE	ok
828
829	// Get error code from libc.
830	CALL	libc_errno(SB)
831	MOVL	(AX), AX
832	MOVW	AX, (9*4)(BX)		// err
833
834ok:
835	MOVL	$0, AX			// no error (it's ignored anyway)
836	MOVL	BP, SP
837	POPL	BP
838	RET
839
840// syscall10 calls a function in libc on behalf of the syscall package.
841// syscall10 takes a pointer to a struct like:
842// struct {
843//	fn    uintptr
844//	a1    uintptr
845//	a2    uintptr
846//	a3    uintptr
847//	a4    uintptr
848//	a5    uintptr
849//	a6    uintptr
850//	a7    uintptr
851//	a8    uintptr
852//	a9    uintptr
853//	a10   uintptr
854//	r1    uintptr
855//	r2    uintptr
856//	err   uintptr
857// }
858// syscall10 must be called on the g0 stack with the
859// C calling convention (use libcCall).
860TEXT runtime·syscall10(SB),NOSPLIT,$0
861	PUSHL	BP
862	MOVL	SP, BP
863
864	SUBL	$40, SP
865	MOVL	48(SP), BX		// pointer to args
866
867	MOVL	(1*4)(BX), AX
868	MOVL	(2*4)(BX), CX
869	MOVL	(3*4)(BX), DX
870	MOVL	AX, (0*4)(SP)		// a1
871	MOVL	CX, (1*4)(SP)		// a2
872	MOVL	DX, (2*4)(SP)		// a3
873	MOVL	(4*4)(BX), AX
874	MOVL	(5*4)(BX), CX
875	MOVL	(6*4)(BX), DX
876	MOVL	AX, (3*4)(SP)		// a4
877	MOVL	CX, (4*4)(SP)		// a5
878	MOVL	DX, (5*4)(SP)		// a6
879	MOVL	(7*4)(BX), AX
880	MOVL	(8*4)(BX), CX
881	MOVL	(9*4)(BX), DX
882	MOVL	AX, (6*4)(SP)		// a7
883	MOVL	CX, (7*4)(SP)		// a8
884	MOVL	DX, (8*4)(SP)		// a9
885	MOVL	(10*4)(BX), AX
886	MOVL	AX, (9*4)(SP)		// a10
887
888	MOVL	(0*4)(BX), AX		// fn
889	CALL	AX
890
891	MOVL	AX, (11*4)(BX)		// r1
892	MOVL	DX, (12*4)(BX)		// r2
893
894	// Standard libc functions return -1 on error and set errno.
895	CMPL	AX, $-1
896	JNE	ok
897
898	// Get error code from libc.
899	CALL	libc_errno(SB)
900	MOVL	(AX), AX
901	MOVW	AX, (13*4)(BX)		// err
902
903ok:
904	MOVL	$0, AX			// no error (it's ignored anyway)
905	MOVL	BP, SP
906	POPL	BP
907	RET
908
909// syscall10X calls a function in libc on behalf of the syscall package.
910// syscall10X takes a pointer to a struct like:
911// struct {
912//	fn    uintptr
913//	a1    uintptr
914//	a2    uintptr
915//	a3    uintptr
916//	a4    uintptr
917//	a5    uintptr
918//	a6    uintptr
919//	a7    uintptr
920//	a8    uintptr
921//	a9    uintptr
922//	a10   uintptr
923//	r1    uintptr
924//	r2    uintptr
925//	err   uintptr
926// }
927// syscall10X must be called on the g0 stack with the
928// C calling convention (use libcCall).
929//
930// syscall10X is like syscall9 but expects a 64-bit result
931// and tests for 64-bit -1 to decide there was an error.
932TEXT runtime·syscall10X(SB),NOSPLIT,$0
933	PUSHL	BP
934	MOVL	SP, BP
935
936	SUBL	$40, SP
937	MOVL	48(SP), BX		// pointer to args
938
939	MOVL	(1*4)(BX), AX
940	MOVL	(2*4)(BX), CX
941	MOVL	(3*4)(BX), DX
942	MOVL	AX, (0*4)(SP)		// a1
943	MOVL	CX, (1*4)(SP)		// a2
944	MOVL	DX, (2*4)(SP)		// a3
945	MOVL	(4*4)(BX), AX
946	MOVL	(5*4)(BX), CX
947	MOVL	(6*4)(BX), DX
948	MOVL	AX, (3*4)(SP)		// a4
949	MOVL	CX, (4*4)(SP)		// a5
950	MOVL	DX, (5*4)(SP)		// a6
951	MOVL	(7*4)(BX), AX
952	MOVL	(8*4)(BX), CX
953	MOVL	(9*4)(BX), DX
954	MOVL	AX, (6*4)(SP)		// a7
955	MOVL	CX, (7*4)(SP)		// a8
956	MOVL	DX, (8*4)(SP)		// a9
957	MOVL	(10*4)(BX), AX
958	MOVL	AX, (9*4)(SP)		// a10
959
960	MOVL	(0*4)(BX), AX		// fn
961	CALL	AX
962
963	MOVL	AX, (11*4)(BX)		// r1
964	MOVL	DX, (12*4)(BX)		// r2
965
966	// Standard libc functions return -1 on error and set errno.
967	CMPL	AX, $-1
968	JNE	ok
969	CMPL	DX, $-1
970	JNE	ok
971
972	// Get error code from libc.
973	CALL	libc_errno(SB)
974	MOVL	(AX), AX
975	MOVW	AX, (13*4)(BX)		// err
976
977ok:
978	MOVL	$0, AX			// no error (it's ignored anyway)
979	MOVL	BP, SP
980	POPL	BP
981	RET
982
983TEXT runtime·issetugid_trampoline(SB),NOSPLIT,$0
984	PUSHL	BP
985	CALL	libc_issetugid(SB)
986	NOP	SP			// tell vet SP changed - stop checking offsets
987	MOVL	8(SP), DX		// pointer to return value
988	MOVL	AX, 0(DX)
989	POPL	BP
990	RET
991