1// Copyright 2013 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, NetBSD
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#define FD_CLOEXEC		1
16#define F_SETFD			2
17
18#define SWI_OS_NETBSD			0xa00000
19#define SYS_exit			SWI_OS_NETBSD | 1
20#define SYS_read			SWI_OS_NETBSD | 3
21#define SYS_write			SWI_OS_NETBSD | 4
22#define SYS_open			SWI_OS_NETBSD | 5
23#define SYS_close			SWI_OS_NETBSD | 6
24#define SYS_getpid			SWI_OS_NETBSD | 20
25#define SYS_kill			SWI_OS_NETBSD | 37
26#define SYS_munmap			SWI_OS_NETBSD | 73
27#define SYS_madvise			SWI_OS_NETBSD | 75
28#define SYS_fcntl			SWI_OS_NETBSD | 92
29#define SYS_mmap			SWI_OS_NETBSD | 197
30#define SYS___sysctl			SWI_OS_NETBSD | 202
31#define SYS___sigaltstack14		SWI_OS_NETBSD | 281
32#define SYS___sigprocmask14		SWI_OS_NETBSD | 293
33#define SYS_getcontext			SWI_OS_NETBSD | 307
34#define SYS_setcontext			SWI_OS_NETBSD | 308
35#define SYS__lwp_create			SWI_OS_NETBSD | 309
36#define SYS__lwp_exit			SWI_OS_NETBSD | 310
37#define SYS__lwp_self			SWI_OS_NETBSD | 311
38#define SYS__lwp_getprivate		SWI_OS_NETBSD | 316
39#define SYS__lwp_setprivate		SWI_OS_NETBSD | 317
40#define SYS__lwp_kill			SWI_OS_NETBSD | 318
41#define SYS__lwp_unpark			SWI_OS_NETBSD | 321
42#define SYS___sigaction_sigtramp	SWI_OS_NETBSD | 340
43#define SYS_kqueue			SWI_OS_NETBSD | 344
44#define SYS_sched_yield			SWI_OS_NETBSD | 350
45#define SYS___setitimer50		SWI_OS_NETBSD | 425
46#define SYS___clock_gettime50		SWI_OS_NETBSD | 427
47#define SYS___nanosleep50		SWI_OS_NETBSD | 430
48#define SYS___kevent50			SWI_OS_NETBSD | 435
49#define SYS____lwp_park60		SWI_OS_NETBSD | 478
50
51// Exit the entire program (like C exit)
52TEXT runtime·exit(SB),NOSPLIT|NOFRAME,$0
53	MOVW code+0(FP), R0	// arg 1 exit status
54	SWI $SYS_exit
55	MOVW.CS $0, R8	// crash on syscall failure
56	MOVW.CS R8, (R8)
57	RET
58
59// func exitThread(wait *uint32)
60TEXT runtime·exitThread(SB),NOSPLIT,$0-4
61	MOVW wait+0(FP), R0
62	// We're done using the stack.
63	MOVW $0, R2
64storeloop:
65	LDREX (R0), R4          // loads R4
66	STREX R2, (R0), R1      // stores R2
67	CMP $0, R1
68	BNE storeloop
69	SWI $SYS__lwp_exit
70	MOVW $1, R8	// crash
71	MOVW R8, (R8)
72	JMP 0(PC)
73
74TEXT runtime·open(SB),NOSPLIT|NOFRAME,$0
75	MOVW name+0(FP), R0
76	MOVW mode+4(FP), R1
77	MOVW perm+8(FP), R2
78	SWI $SYS_open
79	MOVW.CS	$-1, R0
80	MOVW	R0, ret+12(FP)
81	RET
82
83TEXT runtime·closefd(SB),NOSPLIT|NOFRAME,$0
84	MOVW fd+0(FP), R0
85	SWI $SYS_close
86	MOVW.CS	$-1, R0
87	MOVW	R0, ret+4(FP)
88	RET
89
90TEXT runtime·read(SB),NOSPLIT|NOFRAME,$0
91	MOVW fd+0(FP), R0
92	MOVW p+4(FP), R1
93	MOVW n+8(FP), R2
94	SWI $SYS_read
95	RSB.CS	$0, R0		// caller expects negative errno
96	MOVW	R0, ret+12(FP)
97	RET
98
99// func pipe() (r, w int32, errno int32)
100TEXT runtime·pipe(SB),NOSPLIT,$0-12
101	SWI $0xa0002a
102	BCC pipeok
103	MOVW $-1,R2
104	MOVW R2, r+0(FP)
105	MOVW R2, w+4(FP)
106	MOVW R0, errno+8(FP)
107	RET
108pipeok:
109	MOVW $0, R2
110	MOVW R0, r+0(FP)
111	MOVW R1, w+4(FP)
112	MOVW R2, errno+8(FP)
113	RET
114
115// func pipe2(flags int32) (r, w int32, errno int32)
116TEXT runtime·pipe2(SB),NOSPLIT,$0-16
117	MOVW $r+4(FP), R0
118	MOVW flags+0(FP), R1
119	SWI $0xa001c5
120	MOVW R0, errno+12(FP)
121	RET
122
123TEXT runtime·write1(SB),NOSPLIT|NOFRAME,$0
124	MOVW	fd+0(FP), R0	// arg 1 - fd
125	MOVW	p+4(FP), R1	// arg 2 - buf
126	MOVW	n+8(FP), R2	// arg 3 - nbyte
127	SWI $SYS_write
128	RSB.CS	$0, R0		// caller expects negative errno
129	MOVW	R0, ret+12(FP)
130	RET
131
132// int32 lwp_create(void *context, uintptr flags, void *lwpid)
133TEXT runtime·lwp_create(SB),NOSPLIT,$0
134	MOVW ctxt+0(FP), R0
135	MOVW flags+4(FP), R1
136	MOVW lwpid+8(FP), R2
137	SWI $SYS__lwp_create
138	MOVW	R0, ret+12(FP)
139	RET
140
141TEXT runtime·osyield(SB),NOSPLIT,$0
142	SWI $SYS_sched_yield
143	RET
144
145TEXT runtime·lwp_park(SB),NOSPLIT,$8
146	MOVW clockid+0(FP), R0		// arg 1 - clock_id
147	MOVW flags+4(FP), R1		// arg 2 - flags
148	MOVW ts+8(FP), R2		// arg 3 - ts
149	MOVW unpark+12(FP), R3		// arg 4 - unpark
150	MOVW hint+16(FP), R4		// arg 5 - hint
151	MOVW R4, 4(R13)
152	MOVW unparkhint+20(FP), R5	// arg 6 - unparkhint
153	MOVW R5, 8(R13)
154	SWI $SYS____lwp_park60
155	MOVW	R0, ret+24(FP)
156	RET
157
158TEXT runtime·lwp_unpark(SB),NOSPLIT,$0
159	MOVW	lwp+0(FP), R0	// arg 1 - lwp
160	MOVW	hint+4(FP), R1	// arg 2 - hint
161	SWI	$SYS__lwp_unpark
162	MOVW	R0, ret+8(FP)
163	RET
164
165TEXT runtime·lwp_self(SB),NOSPLIT,$0
166	SWI	$SYS__lwp_self
167	MOVW	R0, ret+0(FP)
168	RET
169
170TEXT runtime·lwp_tramp(SB),NOSPLIT,$0
171	MOVW R0, g_m(R1)
172	MOVW R1, g
173
174	BL runtime·emptyfunc(SB) // fault if stack check is wrong
175	BL (R2)
176	MOVW $2, R8  // crash (not reached)
177	MOVW R8, (R8)
178	RET
179
180TEXT runtime·usleep(SB),NOSPLIT,$16
181	MOVW usec+0(FP), R0
182	CALL runtime·usplitR0(SB)
183	// 0(R13) is the saved LR, don't use it
184	MOVW R0, 4(R13) // tv_sec.low
185	MOVW $0, R0
186	MOVW R0, 8(R13) // tv_sec.high
187	MOVW $1000, R2
188	MUL R1, R2
189	MOVW R2, 12(R13) // tv_nsec
190
191	MOVW $4(R13), R0 // arg 1 - rqtp
192	MOVW $0, R1      // arg 2 - rmtp
193	SWI $SYS___nanosleep50
194	RET
195
196TEXT runtime·lwp_kill(SB),NOSPLIT,$0-8
197	MOVW	tid+0(FP), R0	// arg 1 - tid
198	MOVW	sig+4(FP), R1	// arg 2 - signal
199	SWI	$SYS__lwp_kill
200	RET
201
202TEXT runtime·raiseproc(SB),NOSPLIT,$16
203	SWI	$SYS_getpid	// the returned R0 is arg 1
204	MOVW	sig+0(FP), R1	// arg 2 - signal
205	SWI	$SYS_kill
206	RET
207
208TEXT runtime·setitimer(SB),NOSPLIT|NOFRAME,$0
209	MOVW mode+0(FP), R0	// arg 1 - which
210	MOVW new+4(FP), R1	// arg 2 - itv
211	MOVW old+8(FP), R2	// arg 3 - oitv
212	SWI $SYS___setitimer50
213	RET
214
215// func walltime1() (sec int64, nsec int32)
216TEXT runtime·walltime1(SB), NOSPLIT, $32
217	MOVW $0, R0	// CLOCK_REALTIME
218	MOVW $8(R13), R1
219	SWI $SYS___clock_gettime50
220
221	MOVW 8(R13), R0	// sec.low
222	MOVW 12(R13), R1 // sec.high
223	MOVW 16(R13), R2 // nsec
224
225	MOVW R0, sec_lo+0(FP)
226	MOVW R1, sec_hi+4(FP)
227	MOVW R2, nsec+8(FP)
228	RET
229
230// int64 nanotime1(void) so really
231// void nanotime1(int64 *nsec)
232TEXT runtime·nanotime1(SB), NOSPLIT, $32
233	MOVW $3, R0 // CLOCK_MONOTONIC
234	MOVW $8(R13), R1
235	SWI $SYS___clock_gettime50
236
237	MOVW 8(R13), R0 // sec.low
238	MOVW 12(R13), R4 // sec.high
239	MOVW 16(R13), R2 // nsec
240
241	MOVW $1000000000, R3
242	MULLU R0, R3, (R1, R0)
243	MUL R3, R4
244	ADD.S R2, R0
245	ADC R4, R1
246
247	MOVW R0, ret_lo+0(FP)
248	MOVW R1, ret_hi+4(FP)
249	RET
250
251TEXT runtime·getcontext(SB),NOSPLIT|NOFRAME,$0
252	MOVW ctxt+0(FP), R0	// arg 1 - context
253	SWI $SYS_getcontext
254	MOVW.CS $0, R8	// crash on syscall failure
255	MOVW.CS R8, (R8)
256	RET
257
258TEXT runtime·sigprocmask(SB),NOSPLIT,$0
259	MOVW how+0(FP), R0	// arg 1 - how
260	MOVW new+4(FP), R1	// arg 2 - set
261	MOVW old+8(FP), R2	// arg 3 - oset
262	SWI $SYS___sigprocmask14
263	MOVW.CS $0, R8	// crash on syscall failure
264	MOVW.CS R8, (R8)
265	RET
266
267TEXT sigreturn_tramp<>(SB),NOSPLIT|NOFRAME,$0
268	// on entry, SP points to siginfo, we add sizeof(ucontext)
269	// to SP to get a pointer to ucontext.
270	ADD $0x80, R13, R0 // 0x80 == sizeof(UcontextT)
271	SWI $SYS_setcontext
272	// something failed, we have to exit
273	MOVW $0x4242, R0 // magic return number
274	SWI $SYS_exit
275	B -2(PC)	// continue exit
276
277TEXT runtime·sigaction(SB),NOSPLIT,$4
278	MOVW sig+0(FP), R0	// arg 1 - signum
279	MOVW new+4(FP), R1	// arg 2 - nsa
280	MOVW old+8(FP), R2	// arg 3 - osa
281	MOVW $sigreturn_tramp<>(SB), R3	// arg 4 - tramp
282	MOVW $2, R4	// arg 5 - vers
283	MOVW R4, 4(R13)
284	ADD $4, R13	// pass arg 5 on stack
285	SWI $SYS___sigaction_sigtramp
286	SUB $4, R13
287	MOVW.CS $3, R8	// crash on syscall failure
288	MOVW.CS R8, (R8)
289	RET
290
291TEXT runtime·sigfwd(SB),NOSPLIT,$0-16
292	MOVW	sig+4(FP), R0
293	MOVW	info+8(FP), R1
294	MOVW	ctx+12(FP), R2
295	MOVW	fn+0(FP), R11
296	MOVW	R13, R4
297	SUB	$24, R13
298	BIC	$0x7, R13 // alignment for ELF ABI
299	BL	(R11)
300	MOVW	R4, R13
301	RET
302
303TEXT runtime·sigtramp(SB),NOSPLIT,$0
304	// Reserve space for callee-save registers and arguments.
305	MOVM.DB.W [R4-R11], (R13)
306	SUB	$16, R13
307
308	// this might be called in external code context,
309	// where g is not set.
310	// first save R0, because runtime·load_g will clobber it
311	MOVW	R0, 4(R13) // signum
312	MOVB	runtime·iscgo(SB), R0
313	CMP 	$0, R0
314	BL.NE	runtime·load_g(SB)
315
316	MOVW	R1, 8(R13)
317	MOVW	R2, 12(R13)
318	BL	runtime·sigtrampgo(SB)
319
320	// Restore callee-save registers.
321	ADD	$16, R13
322	MOVM.IA.W (R13), [R4-R11]
323
324	RET
325
326TEXT runtime·mmap(SB),NOSPLIT,$12
327	MOVW addr+0(FP), R0	// arg 1 - addr
328	MOVW n+4(FP), R1	// arg 2 - len
329	MOVW prot+8(FP), R2	// arg 3 - prot
330	MOVW flags+12(FP), R3	// arg 4 - flags
331	// arg 5 (fid) and arg6 (offset_lo, offset_hi) are passed on stack
332	// note the C runtime only passes the 32-bit offset_lo to us
333	MOVW fd+16(FP), R4		// arg 5
334	MOVW R4, 4(R13)
335	MOVW off+20(FP), R5		// arg 6 lower 32-bit
336	MOVW R5, 8(R13)
337	MOVW $0, R6 // higher 32-bit for arg 6
338	MOVW R6, 12(R13)
339	ADD $4, R13 // pass arg 5 and arg 6 on stack
340	SWI $SYS_mmap
341	SUB $4, R13
342	MOVW	$0, R1
343	MOVW.CS R0, R1	// if error, move to R1
344	MOVW.CS $0, R0
345	MOVW	R0, p+24(FP)
346	MOVW	R1, err+28(FP)
347	RET
348
349TEXT runtime·munmap(SB),NOSPLIT,$0
350	MOVW addr+0(FP), R0	// arg 1 - addr
351	MOVW n+4(FP), R1	// arg 2 - len
352	SWI $SYS_munmap
353	MOVW.CS $0, R8	// crash on syscall failure
354	MOVW.CS R8, (R8)
355	RET
356
357TEXT runtime·madvise(SB),NOSPLIT,$0
358	MOVW	addr+0(FP), R0	// arg 1 - addr
359	MOVW	n+4(FP), R1	// arg 2 - len
360	MOVW	flags+8(FP), R2	// arg 3 - behav
361	SWI	$SYS_madvise
362	MOVW.CS	$-1, R0
363	MOVW	R0, ret+12(FP)
364	RET
365
366TEXT runtime·sigaltstack(SB),NOSPLIT|NOFRAME,$0
367	MOVW new+0(FP), R0	// arg 1 - nss
368	MOVW old+4(FP), R1	// arg 2 - oss
369	SWI $SYS___sigaltstack14
370	MOVW.CS $0, R8	// crash on syscall failure
371	MOVW.CS R8, (R8)
372	RET
373
374TEXT runtime·sysctl(SB),NOSPLIT,$8
375	MOVW mib+0(FP), R0	// arg 1 - name
376	MOVW miblen+4(FP), R1	// arg 2 - namelen
377	MOVW out+8(FP), R2	// arg 3 - oldp
378	MOVW size+12(FP), R3	// arg 4 - oldlenp
379	MOVW dst+16(FP), R4	// arg 5 - newp
380	MOVW R4, 4(R13)
381	MOVW ndst+20(FP), R4	// arg 6 - newlen
382	MOVW R4, 8(R13)
383	ADD $4, R13	// pass arg 5 and 6 on stack
384	SWI $SYS___sysctl
385	SUB $4, R13
386	MOVW	R0, ret+24(FP)
387	RET
388
389// int32 runtime·kqueue(void)
390TEXT runtime·kqueue(SB),NOSPLIT,$0
391	SWI	$SYS_kqueue
392	RSB.CS	$0, R0
393	MOVW	R0, ret+0(FP)
394	RET
395
396// int32 runtime·kevent(int kq, Kevent *changelist, int nchanges, Kevent *eventlist, int nevents, Timespec *timeout)
397TEXT runtime·kevent(SB),NOSPLIT,$8
398	MOVW kq+0(FP), R0	// kq
399	MOVW ch+4(FP), R1	// changelist
400	MOVW nch+8(FP), R2	// nchanges
401	MOVW ev+12(FP), R3	// eventlist
402	MOVW nev+16(FP), R4	// nevents
403	MOVW R4, 4(R13)
404	MOVW ts+20(FP), R4	// timeout
405	MOVW R4, 8(R13)
406	ADD $4, R13	// pass arg 5 and 6 on stack
407	SWI $SYS___kevent50
408	RSB.CS $0, R0
409	SUB $4, R13
410	MOVW	R0, ret+24(FP)
411	RET
412
413// void runtime·closeonexec(int32 fd)
414TEXT runtime·closeonexec(SB),NOSPLIT,$0
415	MOVW fd+0(FP), R0	// fd
416	MOVW $F_SETFD, R1	// F_SETFD
417	MOVW $FD_CLOEXEC, R2	// FD_CLOEXEC
418	SWI $SYS_fcntl
419	RET
420
421// func runtime·setNonblock(fd int32)
422TEXT runtime·setNonblock(SB),NOSPLIT,$0-4
423	MOVW fd+0(FP), R0	// fd
424	MOVW $3, R1	// F_GETFL
425	MOVW $0, R2
426	SWI $0xa0005c	// sys_fcntl
427	ORR $0x4, R0, R2	// O_NONBLOCK
428	MOVW fd+0(FP), R0	// fd
429	MOVW $4, R1	// F_SETFL
430	SWI $0xa0005c	// sys_fcntl
431	RET
432
433// TODO: this is only valid for ARMv7+
434TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
435	B	runtime·armPublicationBarrier(SB)
436
437TEXT runtime·read_tls_fallback(SB),NOSPLIT|NOFRAME,$0
438	MOVM.WP [R1, R2, R3, R12], (R13)
439	SWI $SYS__lwp_getprivate
440	MOVM.IAW    (R13), [R1, R2, R3, R12]
441	RET
442