1// Copyright 2014 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//go:build linux && (ppc64 || ppc64le)
6
7//
8// System calls and other sys.stuff for ppc64, Linux
9//
10
11#include "go_asm.h"
12#include "go_tls.h"
13#include "textflag.h"
14#include "asm_ppc64x.h"
15#include "cgo/abi_ppc64x.h"
16
17#define SYS_exit		  1
18#define SYS_read		  3
19#define SYS_write		  4
20#define SYS_open		  5
21#define SYS_close		  6
22#define SYS_getpid		 20
23#define SYS_kill		 37
24#define SYS_brk			 45
25#define SYS_mmap		 90
26#define SYS_munmap		 91
27#define SYS_setitimer		104
28#define SYS_clone		120
29#define SYS_sched_yield		158
30#define SYS_nanosleep		162
31#define SYS_rt_sigreturn	172
32#define SYS_rt_sigaction	173
33#define SYS_rt_sigprocmask	174
34#define SYS_sigaltstack		185
35#define SYS_madvise		205
36#define SYS_mincore		206
37#define SYS_gettid		207
38#define SYS_futex		221
39#define SYS_sched_getaffinity	223
40#define SYS_exit_group		234
41#define SYS_timer_create	240
42#define SYS_timer_settime	241
43#define SYS_timer_delete	244
44#define SYS_clock_gettime	246
45#define SYS_tgkill		250
46#define SYS_pipe2		317
47
48TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0-4
49	MOVW	code+0(FP), R3
50	SYSCALL	$SYS_exit_group
51	RET
52
53// func exitThread(wait *atomic.Uint32)
54TEXT runtime·exitThread(SB),NOSPLIT|NOFRAME,$0-8
55	MOVD	wait+0(FP), R1
56	// We're done using the stack.
57	MOVW	$0, R2
58	SYNC
59	MOVW	R2, (R1)
60	MOVW	$0, R3	// exit code
61	SYSCALL	$SYS_exit
62	JMP	0(PC)
63
64TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0-20
65	MOVD	name+0(FP), R3
66	MOVW	mode+8(FP), R4
67	MOVW	perm+12(FP), R5
68	SYSCALL	$SYS_open
69	BVC	2(PC)
70	MOVW	$-1, R3
71	MOVW	R3, ret+16(FP)
72	RET
73
74TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0-12
75	MOVW	fd+0(FP), R3
76	SYSCALL	$SYS_close
77	BVC	2(PC)
78	MOVW	$-1, R3
79	MOVW	R3, ret+8(FP)
80	RET
81
82TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0-28
83	MOVD	fd+0(FP), R3
84	MOVD	p+8(FP), R4
85	MOVW	n+16(FP), R5
86	SYSCALL	$SYS_write
87	BVC	2(PC)
88	NEG	R3	// caller expects negative errno
89	MOVW	R3, ret+24(FP)
90	RET
91
92TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0-28
93	MOVW	fd+0(FP), R3
94	MOVD	p+8(FP), R4
95	MOVW	n+16(FP), R5
96	SYSCALL	$SYS_read
97	BVC	2(PC)
98	NEG	R3	// caller expects negative errno
99	MOVW	R3, ret+24(FP)
100	RET
101
102// func pipe2(flags int32) (r, w int32, errno int32)
103TEXT runtime·pipe2(SB),NOSPLIT|NOFRAME,$0-20
104	ADD	$FIXED_FRAME+8, R1, R3
105	MOVW	flags+0(FP), R4
106	SYSCALL	$SYS_pipe2
107	MOVW	R3, errno+16(FP)
108	RET
109
110// func usleep(usec uint32)
111TEXT runtime·usleep(SB),NOSPLIT,$16-4
112	MOVW	usec+0(FP), R3
113
114	// Use magic constant 0x8637bd06 and shift right 51
115	// to perform usec/1000000.
116	MOVD	$0x8637bd06, R4
117	MULLD	R3, R4, R4	// Convert usec to S.
118	SRD	$51, R4, R4
119	MOVD	R4, 8(R1)	// Store to tv_sec
120
121	MOVD	$1000000, R5
122	MULLW	R4, R5, R5	// Convert tv_sec back into uS
123	SUB	R5, R3, R5	// Compute remainder uS.
124	MULLD	$1000, R5, R5	// Convert to nsec
125	MOVD	R5, 16(R1)	// Store to tv_nsec
126
127	// nanosleep(&ts, 0)
128	ADD	$8, R1, R3
129	MOVW	$0, R4
130	SYSCALL	$SYS_nanosleep
131	RET
132
133TEXT runtime·gettid(SB),NOSPLIT,$0-4
134	SYSCALL	$SYS_gettid
135	MOVW	R3, ret+0(FP)
136	RET
137
138TEXT runtime·raise(SB),NOSPLIT|NOFRAME,$0
139	SYSCALL	$SYS_getpid
140	MOVW	R3, R14
141	SYSCALL	$SYS_gettid
142	MOVW	R3, R4	// arg 2 tid
143	MOVW	R14, R3	// arg 1 pid
144	MOVW	sig+0(FP), R5	// arg 3
145	SYSCALL	$SYS_tgkill
146	RET
147
148TEXT runtime·raiseproc(SB),NOSPLIT|NOFRAME,$0
149	SYSCALL	$SYS_getpid
150	MOVW	R3, R3	// arg 1 pid
151	MOVW	sig+0(FP), R4	// arg 2
152	SYSCALL	$SYS_kill
153	RET
154
155TEXT ·getpid(SB),NOSPLIT|NOFRAME,$0-8
156	SYSCALL $SYS_getpid
157	MOVD	R3, ret+0(FP)
158	RET
159
160TEXT ·tgkill(SB),NOSPLIT|NOFRAME,$0-24
161	MOVD	tgid+0(FP), R3
162	MOVD	tid+8(FP), R4
163	MOVD	sig+16(FP), R5
164	SYSCALL $SYS_tgkill
165	RET
166
167TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0-24
168	MOVW	mode+0(FP), R3
169	MOVD	new+8(FP), R4
170	MOVD	old+16(FP), R5
171	SYSCALL	$SYS_setitimer
172	RET
173
174TEXT runtime·timer_create(SB),NOSPLIT,$0-28
175	MOVW	clockid+0(FP), R3
176	MOVD	sevp+8(FP), R4
177	MOVD	timerid+16(FP), R5
178	SYSCALL	$SYS_timer_create
179	MOVW	R3, ret+24(FP)
180	RET
181
182TEXT runtime·timer_settime(SB),NOSPLIT,$0-28
183	MOVW	timerid+0(FP), R3
184	MOVW	flags+4(FP), R4
185	MOVD	new+8(FP), R5
186	MOVD	old+16(FP), R6
187	SYSCALL	$SYS_timer_settime
188	MOVW	R3, ret+24(FP)
189	RET
190
191TEXT runtime·timer_delete(SB),NOSPLIT,$0-12
192	MOVW	timerid+0(FP), R3
193	SYSCALL	$SYS_timer_delete
194	MOVW	R3, ret+8(FP)
195	RET
196
197TEXT runtime·mincore(SB),NOSPLIT|NOFRAME,$0-28
198	MOVD	addr+0(FP), R3
199	MOVD	n+8(FP), R4
200	MOVD	dst+16(FP), R5
201	SYSCALL	$SYS_mincore
202	NEG	R3		// caller expects negative errno
203	MOVW	R3, ret+24(FP)
204	RET
205
206// func walltime() (sec int64, nsec int32)
207TEXT runtime·walltime(SB),NOSPLIT,$16-12
208	MOVD	R1, R15		// R15 is unchanged by C code
209	MOVD	g_m(g), R21	// R21 = m
210
211	MOVD	$0, R3		// CLOCK_REALTIME
212
213	MOVD	runtime·vdsoClockgettimeSym(SB), R12	// Check for VDSO availability
214	CMP	R12, $0
215	BEQ	fallback
216
217	// Set vdsoPC and vdsoSP for SIGPROF traceback.
218	// Save the old values on stack and restore them on exit,
219	// so this function is reentrant.
220	MOVD	m_vdsoPC(R21), R4
221	MOVD	m_vdsoSP(R21), R5
222	MOVD	R4, 32(R1)
223	MOVD	R5, 40(R1)
224
225	MOVD	LR, R14
226	MOVD	$ret-FIXED_FRAME(FP), R5 // caller's SP
227	MOVD	R14, m_vdsoPC(R21)
228	MOVD	R5, m_vdsoSP(R21)
229
230	MOVD	m_curg(R21), R6
231	CMP	g, R6
232	BNE	noswitch
233
234	MOVD	m_g0(R21), R7
235	MOVD	(g_sched+gobuf_sp)(R7), R1	// Set SP to g0 stack
236
237noswitch:
238	SUB	$16, R1                 // Space for results
239	RLDICR	$0, R1, $59, R1         // Align for C code
240	MOVD	R12, CTR
241	MOVD	R1, R4
242
243	// Store g on gsignal's stack, so if we receive a signal
244	// during VDSO code we can find the g.
245	// If we don't have a signal stack, we won't receive signal,
246	// so don't bother saving g.
247	// When using cgo, we already saved g on TLS, also don't save
248	// g here.
249	// Also don't save g if we are already on the signal stack.
250	// We won't get a nested signal.
251	MOVBZ	runtime·iscgo(SB), R22
252	CMP	R22, $0
253	BNE	nosaveg
254	MOVD	m_gsignal(R21), R22	// g.m.gsignal
255	CMP	R22, $0
256	BEQ	nosaveg
257
258	CMP	g, R22
259	BEQ	nosaveg
260	MOVD	(g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
261	MOVD	g, (R22)
262
263	BL	(CTR)	// Call from VDSO
264
265	MOVD	$0, (R22)	// clear g slot, R22 is unchanged by C code
266
267	JMP	finish
268
269nosaveg:
270	BL	(CTR)	// Call from VDSO
271
272finish:
273	MOVD	$0, R0		// Restore R0
274	MOVD	0(R1), R3	// sec
275	MOVD	8(R1), R5	// nsec
276	MOVD	R15, R1		// Restore SP
277
278	// Restore vdsoPC, vdsoSP
279	// We don't worry about being signaled between the two stores.
280	// If we are not in a signal handler, we'll restore vdsoSP to 0,
281	// and no one will care about vdsoPC. If we are in a signal handler,
282	// we cannot receive another signal.
283	MOVD	40(R1), R6
284	MOVD	R6, m_vdsoSP(R21)
285	MOVD	32(R1), R6
286	MOVD	R6, m_vdsoPC(R21)
287
288return:
289	MOVD	R3, sec+0(FP)
290	MOVW	R5, nsec+8(FP)
291	RET
292
293	// Syscall fallback
294fallback:
295	ADD	$32, R1, R4
296	SYSCALL $SYS_clock_gettime
297	MOVD	32(R1), R3
298	MOVD	40(R1), R5
299	JMP	return
300
301TEXT runtime·nanotime1(SB),NOSPLIT,$16-8
302	MOVD	$1, R3		// CLOCK_MONOTONIC
303
304	MOVD	R1, R15		// R15 is unchanged by C code
305	MOVD	g_m(g), R21	// R21 = m
306
307	MOVD	runtime·vdsoClockgettimeSym(SB), R12	// Check for VDSO availability
308	CMP	R12, $0
309	BEQ	fallback
310
311	// Set vdsoPC and vdsoSP for SIGPROF traceback.
312	// Save the old values on stack and restore them on exit,
313	// so this function is reentrant.
314	MOVD	m_vdsoPC(R21), R4
315	MOVD	m_vdsoSP(R21), R5
316	MOVD	R4, 32(R1)
317	MOVD	R5, 40(R1)
318
319	MOVD	LR, R14				// R14 is unchanged by C code
320	MOVD	$ret-FIXED_FRAME(FP), R5	// caller's SP
321	MOVD	R14, m_vdsoPC(R21)
322	MOVD	R5, m_vdsoSP(R21)
323
324	MOVD	m_curg(R21), R6
325	CMP	g, R6
326	BNE	noswitch
327
328	MOVD	m_g0(R21), R7
329	MOVD	(g_sched+gobuf_sp)(R7), R1	// Set SP to g0 stack
330
331noswitch:
332	SUB	$16, R1			// Space for results
333	RLDICR	$0, R1, $59, R1		// Align for C code
334	MOVD	R12, CTR
335	MOVD	R1, R4
336
337	// Store g on gsignal's stack, so if we receive a signal
338	// during VDSO code we can find the g.
339	// If we don't have a signal stack, we won't receive signal,
340	// so don't bother saving g.
341	// When using cgo, we already saved g on TLS, also don't save
342	// g here.
343	// Also don't save g if we are already on the signal stack.
344	// We won't get a nested signal.
345	MOVBZ	runtime·iscgo(SB), R22
346	CMP	R22, $0
347	BNE	nosaveg
348	MOVD	m_gsignal(R21), R22	// g.m.gsignal
349	CMP	R22, $0
350	BEQ	nosaveg
351
352	CMP	g, R22
353	BEQ	nosaveg
354	MOVD	(g_stack+stack_lo)(R22), R22 // g.m.gsignal.stack.lo
355	MOVD	g, (R22)
356
357	BL	(CTR)	// Call from VDSO
358
359	MOVD	$0, (R22)	// clear g slot, R22 is unchanged by C code
360
361	JMP	finish
362
363nosaveg:
364	BL	(CTR)	// Call from VDSO
365
366finish:
367	MOVD	$0, R0			// Restore R0
368	MOVD	0(R1), R3		// sec
369	MOVD	8(R1), R5		// nsec
370	MOVD	R15, R1			// Restore SP
371
372	// Restore vdsoPC, vdsoSP
373	// We don't worry about being signaled between the two stores.
374	// If we are not in a signal handler, we'll restore vdsoSP to 0,
375	// and no one will care about vdsoPC. If we are in a signal handler,
376	// we cannot receive another signal.
377	MOVD	40(R1), R6
378	MOVD	R6, m_vdsoSP(R21)
379	MOVD	32(R1), R6
380	MOVD	R6, m_vdsoPC(R21)
381
382return:
383	// sec is in R3, nsec in R5
384	// return nsec in R3
385	MOVD	$1000000000, R4
386	MULLD	R4, R3
387	ADD	R5, R3
388	MOVD	R3, ret+0(FP)
389	RET
390
391	// Syscall fallback
392fallback:
393	ADD	$32, R1, R4
394	SYSCALL $SYS_clock_gettime
395	MOVD	32(R1), R3
396	MOVD	40(R1), R5
397	JMP	return
398
399TEXT runtime·rtsigprocmask(SB),NOSPLIT|NOFRAME,$0-28
400	MOVW	how+0(FP), R3
401	MOVD	new+8(FP), R4
402	MOVD	old+16(FP), R5
403	MOVW	size+24(FP), R6
404	SYSCALL	$SYS_rt_sigprocmask
405	BVC	2(PC)
406	MOVD	R0, 0xf0(R0)	// crash
407	RET
408
409TEXT runtime·rt_sigaction(SB),NOSPLIT|NOFRAME,$0-36
410	MOVD	sig+0(FP), R3
411	MOVD	new+8(FP), R4
412	MOVD	old+16(FP), R5
413	MOVD	size+24(FP), R6
414	SYSCALL	$SYS_rt_sigaction
415	BVC	2(PC)
416	NEG	R3	// caller expects negative errno
417	MOVW	R3, ret+32(FP)
418	RET
419
420#ifdef GOARCH_ppc64le
421// Call the function stored in _cgo_sigaction using the GCC calling convention.
422TEXT runtime·callCgoSigaction(SB),NOSPLIT,$0
423	MOVD    sig+0(FP), R3
424	MOVD    new+8(FP), R4
425	MOVD    old+16(FP), R5
426	MOVD     _cgo_sigaction(SB), R12
427	MOVD    R12, CTR                // R12 should contain the function address
428	MOVD    R1, R15                 // Save R1
429	MOVD    R2, 24(R1)              // Save R2
430	SUB     $48, R1                 // reserve 32 (frame) + 16 bytes for sp-8 where fp may be saved.
431	RLDICR  $0, R1, $59, R1         // Align to 16 bytes for C code
432	BL      (CTR)
433	XOR     R0, R0, R0              // Clear R0 as Go expects
434	MOVD    R15, R1                 // Restore R1
435	MOVD    24(R1), R2              // Restore R2
436	MOVW    R3, ret+24(FP)          // Return result
437	RET
438#endif
439
440TEXT runtime·sigfwd(SB),NOSPLIT,$0-32
441	MOVW	sig+8(FP), R3
442	MOVD	info+16(FP), R4
443	MOVD	ctx+24(FP), R5
444	MOVD	fn+0(FP), R12
445	MOVD	R12, CTR
446	BL	(CTR)
447	MOVD	24(R1), R2
448	RET
449
450#ifdef GO_PPC64X_HAS_FUNCDESC
451DEFINE_PPC64X_FUNCDESC(runtime·sigtramp, sigtramp<>)
452// cgo isn't supported on ppc64, but we need to supply a cgoSigTramp function.
453DEFINE_PPC64X_FUNCDESC(runtime·cgoSigtramp, sigtramp<>)
454TEXT sigtramp<>(SB),NOSPLIT|NOFRAME|TOPFRAME,$0
455#else
456// ppc64le doesn't need function descriptors
457// Save callee-save registers in the case of signal forwarding.
458// Same as on ARM64 https://golang.org/issue/31827 .
459//
460// Note, it is assumed this is always called indirectly (e.g via
461// a function pointer) as R2 may not be preserved when calling this
462// function. In those cases, the caller preserves their R2.
463TEXT runtime·sigtramp(SB),NOSPLIT|NOFRAME,$0
464#endif
465	// This is called with ELF calling conventions. Convert to Go.
466	// Allocate space for argument storage to call runtime.sigtrampgo.
467	STACK_AND_SAVE_HOST_TO_GO_ABI(32)
468
469	// this might be called in external code context,
470	// where g is not set.
471	MOVBZ	runtime·iscgo(SB), R6
472	CMP	R6, $0
473	BEQ	2(PC)
474	BL	runtime·load_g(SB)
475
476	// R3,R4,R5 already hold the arguments. Forward them on.
477	// TODO: Indirectly call runtime.sigtrampgo to avoid the linker's static NOSPLIT stack
478	// overflow detection. It thinks this might be called on a small Go stack, but this is only
479	// called from a larger pthread or sigaltstack stack. Can the checker be improved to not
480	// flag a direct call here?
481	MOVD	$runtime·sigtrampgo<ABIInternal>(SB), R12
482	MOVD	R12, CTR
483	BL	(CTR)
484	// Restore R2 (TOC pointer) in the event it might be used later in this function.
485	// If this was not compiled as shared code, R2 is undefined, reloading it is harmless.
486	MOVD	24(R1), R2
487
488	UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(32)
489	RET
490
491#ifdef GOARCH_ppc64le
492TEXT runtime·cgoSigtramp(SB),NOSPLIT|NOFRAME,$0
493	// The stack unwinder, presumably written in C, may not be able to
494	// handle Go frame correctly. So, this function is NOFRAME, and we
495	// save/restore LR manually, and obey ELFv2 calling conventions.
496	MOVD	LR, R10
497
498	// We're coming from C code, initialize R0
499	MOVD	$0, R0
500
501	// If no traceback function, do usual sigtramp.
502	MOVD	runtime·cgoTraceback(SB), R6
503	CMP	$0, R6
504	BEQ	sigtramp
505
506	// If no traceback support function, which means that
507	// runtime/cgo was not linked in, do usual sigtramp.
508	MOVD	_cgo_callers(SB), R6
509	CMP	$0, R6
510	BEQ	sigtramp
511
512	// Inspect the g in TLS without clobbering R30/R31 via runtime.load_g.
513	MOVD	runtime·tls_g(SB), R9
514	MOVD	0(R9), R9
515
516	// Figure out if we are currently in a cgo call.
517	// If not, just do usual sigtramp.
518	// compared to ARM64 and others.
519	CMP	$0, R9
520	BEQ	sigtrampnog // g == nil
521
522	// g is not nil. Check further.
523	MOVD	g_m(R9), R6
524	CMP	$0, R6
525	BEQ	sigtramp    // g.m == nil
526	MOVW	m_ncgo(R6), R7
527	CMPW	$0, R7
528	BEQ	sigtramp    // g.m.ncgo = 0
529	MOVD	m_curg(R6), R7
530	CMP	$0, R7
531	BEQ	sigtramp    // g.m.curg == nil
532	MOVD	g_syscallsp(R7), R7
533	CMP	$0, R7
534	BEQ	sigtramp    // g.m.curg.syscallsp == 0
535	MOVD	m_cgoCallers(R6), R7 // R7 is the fifth arg in C calling convention.
536	CMP	$0, R7
537	BEQ	sigtramp    // g.m.cgoCallers == nil
538	MOVW	m_cgoCallersUse(R6), R8
539	CMPW	$0, R8
540	BNE	sigtramp    // g.m.cgoCallersUse != 0
541
542	// Jump to a function in runtime/cgo.
543	// That function, written in C, will call the user's traceback
544	// function with proper unwind info, and will then call back here.
545	// The first three arguments, and the fifth, are already in registers.
546	// Set the two remaining arguments now.
547	MOVD	runtime·cgoTraceback(SB), R6
548	MOVD	$runtime·sigtramp(SB), R8
549	MOVD	_cgo_callers(SB), R12
550	MOVD	R12, CTR
551	MOVD	R10, LR // restore LR
552	JMP	(CTR)
553
554sigtramp:
555	MOVD	R10, LR // restore LR
556	JMP	runtime·sigtramp(SB)
557
558sigtrampnog:
559	// Signal arrived on a non-Go thread. If this is SIGPROF, get a
560	// stack trace.
561	CMPW	R3, $27 // 27 == SIGPROF
562	BNE	sigtramp
563
564	// Lock sigprofCallersUse (cas from 0 to 1).
565	MOVW	$1, R7
566	MOVD	$runtime·sigprofCallersUse(SB), R8
567	SYNC
568	LWAR    (R8), R6
569	CMPW    $0, R6
570	BNE     sigtramp
571	STWCCC  R7, (R8)
572	BNE     -4(PC)
573	ISYNC
574
575	// Jump to the traceback function in runtime/cgo.
576	// It will call back to sigprofNonGo, which will ignore the
577	// arguments passed in registers.
578	// First three arguments to traceback function are in registers already.
579	MOVD	runtime·cgoTraceback(SB), R6
580	MOVD	$runtime·sigprofCallers(SB), R7
581	MOVD	$runtime·sigprofNonGoWrapper<>(SB), R8
582	MOVD	_cgo_callers(SB), R12
583	MOVD	R12, CTR
584	MOVD	R10, LR // restore LR
585	JMP	(CTR)
586#endif
587
588// Used by cgoSigtramp to inspect without clobbering R30/R31 via runtime.load_g.
589GLOBL runtime·tls_g+0(SB), TLSBSS+DUPOK, $8
590
591TEXT runtime·sigprofNonGoWrapper<>(SB),NOSPLIT|NOFRAME,$0
592	// This is called from C code. Callee save registers must be saved.
593	// R3,R4,R5 hold arguments, and allocate argument space to call sigprofNonGo.
594	STACK_AND_SAVE_HOST_TO_GO_ABI(32)
595
596	CALL	runtime·sigprofNonGo<ABIInternal>(SB)
597
598	UNSTACK_AND_RESTORE_GO_TO_HOST_ABI(32)
599	RET
600
601TEXT runtime·mmap(SB),NOSPLIT|NOFRAME,$0
602	MOVD	addr+0(FP), R3
603	MOVD	n+8(FP), R4
604	MOVW	prot+16(FP), R5
605	MOVW	flags+20(FP), R6
606	MOVW	fd+24(FP), R7
607	MOVW	off+28(FP), R8
608
609	SYSCALL	$SYS_mmap
610	BVC	ok
611	MOVD	$0, p+32(FP)
612	MOVD	R3, err+40(FP)
613	RET
614ok:
615	MOVD	R3, p+32(FP)
616	MOVD	$0, err+40(FP)
617	RET
618
619TEXT runtime·munmap(SB),NOSPLIT|NOFRAME,$0
620	MOVD	addr+0(FP), R3
621	MOVD	n+8(FP), R4
622	SYSCALL	$SYS_munmap
623	BVC	2(PC)
624	MOVD	R0, 0xf0(R0)
625	RET
626
627TEXT runtime·madvise(SB),NOSPLIT|NOFRAME,$0
628	MOVD	addr+0(FP), R3
629	MOVD	n+8(FP), R4
630	MOVW	flags+16(FP), R5
631	SYSCALL	$SYS_madvise
632	MOVW	R3, ret+24(FP)
633	RET
634
635// int64 futex(int32 *uaddr, int32 op, int32 val,
636//	struct timespec *timeout, int32 *uaddr2, int32 val2);
637TEXT runtime·futex(SB),NOSPLIT|NOFRAME,$0
638	MOVD	addr+0(FP), R3
639	MOVW	op+8(FP), R4
640	MOVW	val+12(FP), R5
641	MOVD	ts+16(FP), R6
642	MOVD	addr2+24(FP), R7
643	MOVW	val3+32(FP), R8
644	SYSCALL	$SYS_futex
645	BVC	2(PC)
646	NEG	R3	// caller expects negative errno
647	MOVW	R3, ret+40(FP)
648	RET
649
650// int64 clone(int32 flags, void *stk, M *mp, G *gp, void (*fn)(void));
651TEXT runtime·clone(SB),NOSPLIT|NOFRAME,$0
652	MOVW	flags+0(FP), R3
653	MOVD	stk+8(FP), R4
654
655	// Copy mp, gp, fn off parent stack for use by child.
656	// Careful: Linux system call clobbers ???.
657	MOVD	mp+16(FP), R7
658	MOVD	gp+24(FP), R8
659	MOVD	fn+32(FP), R12
660
661	MOVD	R7, -8(R4)
662	MOVD	R8, -16(R4)
663	MOVD	R12, -24(R4)
664	MOVD	$1234, R7
665	MOVD	R7, -32(R4)
666
667	SYSCALL $SYS_clone
668	BVC	2(PC)
669	NEG	R3	// caller expects negative errno
670
671	// In parent, return.
672	CMP	R3, $0
673	BEQ	3(PC)
674	MOVW	R3, ret+40(FP)
675	RET
676
677	// In child, on new stack.
678	// initialize essential registers
679	BL	runtime·reginit(SB)
680	MOVD	-32(R1), R7
681	CMP	R7, $1234
682	BEQ	2(PC)
683	MOVD	R0, 0(R0)
684
685	// Initialize m->procid to Linux tid
686	SYSCALL $SYS_gettid
687
688	MOVD	-24(R1), R12       // fn
689	MOVD	-16(R1), R8        // g
690	MOVD	-8(R1), R7         // m
691
692	CMP	R7, $0
693	BEQ	nog
694	CMP	R8, $0
695	BEQ	nog
696
697	MOVD	R3, m_procid(R7)
698
699	// TODO: setup TLS.
700
701	// In child, set up new stack
702	MOVD	R7, g_m(R8)
703	MOVD	R8, g
704	//CALL	runtime·stackcheck(SB)
705
706nog:
707	// Call fn
708	MOVD	R12, CTR
709	BL	(CTR)
710
711	// It shouldn't return.	 If it does, exit that thread.
712	MOVW	$111, R3
713	SYSCALL	$SYS_exit
714	BR	-2(PC)	// keep exiting
715
716TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
717	MOVD	new+0(FP), R3
718	MOVD	old+8(FP), R4
719	SYSCALL	$SYS_sigaltstack
720	BVC	2(PC)
721	MOVD	R0, 0xf0(R0)  // crash
722	RET
723
724TEXT runtime·osyield(SB),NOSPLIT|NOFRAME,$0
725	SYSCALL	$SYS_sched_yield
726	RET
727
728TEXT runtime·sched_getaffinity(SB),NOSPLIT|NOFRAME,$0
729	MOVD	pid+0(FP), R3
730	MOVD	len+8(FP), R4
731	MOVD	buf+16(FP), R5
732	SYSCALL	$SYS_sched_getaffinity
733	BVC	2(PC)
734	NEG	R3	// caller expects negative errno
735	MOVW	R3, ret+24(FP)
736	RET
737
738// func sbrk0() uintptr
739TEXT runtime·sbrk0(SB),NOSPLIT|NOFRAME,$0
740	// Implemented as brk(NULL).
741	MOVD	$0, R3
742	SYSCALL	$SYS_brk
743	MOVD	R3, ret+0(FP)
744	RET
745
746TEXT runtime·access(SB),$0-20
747	MOVD	R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
748	MOVW	R0, ret+16(FP) // for vet
749	RET
750
751TEXT runtime·connect(SB),$0-28
752	MOVD	R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
753	MOVW	R0, ret+24(FP) // for vet
754	RET
755
756TEXT runtime·socket(SB),$0-20
757	MOVD	R0, 0(R0) // unimplemented, only needed for android; declared in stubs_linux.go
758	MOVW	R0, ret+16(FP) // for vet
759	RET
760